Naudingos komandos

S
  • 1
  • 30 Grd '16

Sveiki,

Siūlau šioje temoje dalintis įvairiomis naudingomis komandomis/funcijomis.

Pradėsiu:

Nedestruktyvus man stebėjimas, su Ctrl+h.
papildom .bashrc failą:

function man_on_word {
  # This function lets you non-nondestructively view command man page.
  # usage: press Ctrl-h
    TMP_LN=$READLINE_LINE
    TMP_POS=$READLINE_POINT
    while [ $TMP_POS -gt 0 ] &&
      [ "${TMP_LN:TMP_POS:1}" != " " ]
      do true $((--TMP_POS))
    done
    if [ 0 -ne $TMP_POS ]; then true $((++TMP_POS));fi
    TMP_WORD="${READLINE_LINE:$TMP_POS}"
    TMP_WORD="${TMP_WORD%% *}"
    man "$TMP_WORD"
}
bind -x '"\C-h":man_on_word'
T
Techtronic
Mindaugas N.
  • 1
  • 30 Grd '16

Bash nenaudoju, bet zsh galiu keleta pasidalint

vcs_info

Tarkim dirbti su Git naudoju:

zsh

zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:*' check-for-changes true
zstyle ':vcs_info:*' get-revision true
zstyle ':vcs_info:*' formats "%B%F{34}%b%f%%b%u"
zstyle ':vcs_info:*' actionformats "%B%F{34}%b%f%%b:%K{52}%F{180}%B%a%%b%f%k%u"
# Enable untracked file notifications.
zstyle ':vcs_info:git*+set-message:*' hooks git-untracked
+vi-git-untracked() {
    if [[ $(git rev-parse --is-inside-work-tree 2> /dev/null) == 'true' ]]; then
    MOD=($(git status --porcelain | grep -oE '\s?(D|M|R|A|\?\?)\s'))
    D=0 M=0 R=0 A=0 U=0 PR=""
    for a in ${MOD}; do
        [[ ${a} == "D"  ]] && D=$(($D+1))
        [[ ${a} == "M"  ]] && M=$(($M+1))
        [[ ${a} == "R"  ]] && R=$(($R+1))
        [[ ${a} == "A"  ]] && A=$(($A+1))
        [[ ${a} == "??" ]] && U=$(($U+1))
    done
    add2PR() { [[ -z ${PR} ]] && PR="${1}" || PR+="%B%F{32}|%f%b${1}" }
    [[ ${D} != 0 ]] && add2PR "%F{160}D%f:${D}"
    [[ ${M} != 0 ]] && add2PR "%F{119}M%f:${M}"
    [[ ${R} != 0 ]] && add2PR "%F{148}R%f:${R}"
    [[ ${A} != 0 ]] && add2PR "%F{117}A%f:${A}"
    [[ ${U} != 0 ]] && add2PR "%F{203}U%f:${U}"
    [[ -n ${PR} ]] && {
        hook_com[unstaged]="%B%F{32}[%f%b"
        hook_com[unstaged]+=${PR}
        hook_com[unstaged]+="%B%F{32}]%f%b"
    }
    [[ ${hook_com[subdir]} != '.' ]] && subdir=/${hook_com[subdir]} || unset subdir
    setpwd /${hook_com[base-name]}${subdir}
    fi
}

setpwd yra funkcija kuri atnaujina PWD mano PROMPT'e.

function setpwd() {
    [[ -n ${1} ]] && SEP="${PR_STUFF[PR_SPC]}" || unset SEP
    PR_STUFF[PR_PWD]="${SEP}%F{10}%45<...<${1:=${PWD}}%<<%f"
}

${PR_STUFF[PR_SPC]} yra seperatorius, tarkim PR_STUFF[PR_SPC]=":". Dabar i PS1 galima nurodyti ${PR_STUFF[PR_PWD]}

f

Naudoja find komanda ir tai ka randa nuspalvina:

f

function f() {
    [[ -z ${1} ]] && {
    print "Usage: f '*.log' /tmp"
    } || { [[ ${terminfo[colors]} == "256" ]] && {
            format="[$(echoti setaf 160)%Y$(echoti sgr0)]"
        format+="[$(echoti setaf 70) %M $(echoti sgr0)"
        format+="$(echoti setaf 208)%u$(echoti sgr0):"
        format+="$(echoti setaf 220)%-10g$(echoti sgr0)]"
        format+="[$(echoti setaf 131) %-10s $(echoti sgr0)]"
        format+="$(echoti setaf 32) %h/$(echoti sgr0)"
        format+="$(echoti setaf 38)%f$(echoti sgr0)\n"
    } || format="[%Y][ %M %u:%-10g][ %-10s] %p\n"
    find ${2:=$(pwd)}/ -iname ${1} -printf ${3:=$format}
    }
}
G
  • 31 Grd '16

@Supoplex said:
Nedestruktyvus man stebėjimas, su Ctrl+h.

Gal gali plačiau, ką reiškia Nedestruktyvus man stebėjimas?

S
  • 31 Grd '16

@Ghost said:
Gal gali plačiau, ką reiškia Nedestruktyvus man stebėjimas?

Tarkim terminale rašai kokią nors komandą:
watch -d "df -B MB /dev/sdc1"
ir staiga nori pasižiūrėti komandos reikšmę. Nereikia ištrinti eilutės, tiesiog užeini ties watch ir paspaudi Ctrl+h - atsidaro watch dokumentacija.
Uždarius dokumentacija grįžti prie aukščiau paminėtos watch komandos. Nedestruktyvus, ta prasme, kad nereikia ištrinti komandos, norint pasižiūrėti komandos paaiškinimus. Pasižiūri man, uždarai man ir vėl gyžti prie tos pačios eilutės terminale.

Tuo pačiu, dar viena komanda:
Konvertavimas iš youtube į mp3:
$ youtube-dl --extract-audio --audio-format mp3 <youtube-nuoroda>

G
  • 1
  • 5 Sau '17

Susipažinusiems su Logwatch iššūkiai yra aiškūs ir suprantami.

Prisipažįstu, kad dar neišbandžiau, bet artimiausiu metu ketinu, nes mintis pas juos tikrai gera! Šaltinis:

#!/usr/bin/env python3

from systemd import journal
from datetime import datetime, timedelta
from email.mime.text import MIMEText
import re, smtplib

# First, let's define patterns to ignore.

# Those are for matching dynamically named units:
session = re.compile("session-[a-z]?\d+.scope")
sshUnit = re.compile("sshd@[0-9a-f.:]*")

# Those will match the logged message itself:
sshSocketStart = re.compile("(Starting|Stopping) OpenSSH Per-Connection Daemon.*")
sshAcceptPublicKey = re.compile("Accepted publickey for (bob|alice).*")
sshReceivedDisconnect = re.compile("Received disconnect from.*")
logindNewSession = re.compile("New session [a-z]?\d+ of user (bob|alice).*")
sshdSessionClosed = re.compile(".*session closed for user (bob|alice).*")
sessionOpenedRoot = re.compile(".*session opened for user root.*")
suSessionClosedGit = re.compile(".*session opened for user git.*")
anacronNormalExit = re.compile("Normal exit (\d+ jobs run).*")
postfixStatistics = re.compile("statistics:.*")
postfixHostnameDoesNotResolve = re.compile("warning: hostname .* does not resolve to address .*: Name or service not known")

# Open the journal for reading, set log level and go back one day and 10 minutes
j = journal.Reader()
j.log_level(journal.LOG_INFO)
yesterday = datetime.now() - timedelta(days=1, minutes=10)
j.seek_realtime(yesterday)

# We'll store messages in this variable
mailContent = []

# Filter and store output
for entry in j:
    # Special cases for logs without a message
    if 'MESSAGE' not in entry:
        mailContent.append( 'U %s %s[%s]: EMPTY!' % (
            datetime.ctime(entry['__REALTIME_TIMESTAMP']),
            entry['PRIORITY'],
            entry['SYSLOG_IDENTIFIER'],
        ))

    # With systemd unit name
    elif '_SYSTEMD_UNIT' in entry:
        if entry['PRIORITY'] > 4:
            if entry['_SYSTEMD_UNIT'] == "wtcomments.service":
                pass
            elif entry['_SYSTEMD_UNIT'] == "ffsync.service":
                pass
        elif session.match(entry['_SYSTEMD_UNIT']):
            pass
        elif sshUnit.match(entry['_SYSTEMD_UNIT']):
            if sshAcceptPublicKey.match(entry['MESSAGE']):
                pass
            elif sshReceivedDisconnect.match(entry['MESSAGE']):
                pass
        elif entry['_SYSTEMD_UNIT'] == "systemd-logind.service":
            if logindNewSession.match(entry['MESSAGE']):
                pass
        elif entry['_SYSTEMD_UNIT'] == "postfix.service":
            if postfixHostnameDoesNotResolve.match(entry['MESSAGE']):
                pass
        else:
            mailContent.append( 'U %s %s %s %s[%s]: %s' % (
                datetime.ctime(entry['__REALTIME_TIMESTAMP']),
                entry['PRIORITY'],
                entry['_SYSTEMD_UNIT'],
                entry['SYSLOG_IDENTIFIER'],
                entry['_PID'],
                entry['MESSAGE']
            ))

    # With syslog identifier only
    elif entry['SYSLOG_IDENTIFIER'] == "systemd":
        if sshSocketStart.match(entry['MESSAGE']):
            pass
        elif firewalldStart.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "sshd":
        if sshdSessionClosed.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "sudo":
        if sessionOpenedRoot.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "CROND":
        if sessionOpenedRoot.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "anacron":
        if anacronNormalExit.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "postfix/anvil":
        if postfixStatistics.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "su":
        if suSessionClosedGit.match(entry['MESSAGE']):
            pass
    else:
        mailContent.append( 'S %s %s %s: %s' % (
            datetime.ctime(entry['__REALTIME_TIMESTAMP']),
            entry['PRIORITY'],
            entry['SYSLOG_IDENTIFIER'],
            entry['MESSAGE']
        ))

# Send the content in a mail to root
mail = MIMEText('\n'.join(mailContent))
mail['Subject'] = '[example.com] Logs from ' + datetime.ctime(yesterday) + ' to ' + datetime.ctime(datetime.now())
mail['From'] = 'journald@example.com'
mail['To'] = 'root@example.com'
server = smtplib.SMTP('localhost')
server.send_message(mail)
server.quit()
T
Techtronic
Mindaugas N.
  • 2
  • 6 Sau '17

Su Logwatch ne, bet su Elasticsearch, Logstash ir Kibana teko bandrauti

a

Source https://ubuntu.lt/topic/8589/ulog-elasticsearch-logstash-kibana/

Dar noreciau prie tokio stuff patarti viena utilita kuri daug metu naudoju - Multitail

T
Techtronic
Mindaugas N.
  • 1
  • 6 Sau '17

Paskutiniu metu tapo sudetinga naudoti KDE, taip yra todel kad daugeli savo biblioteku jie isskleide i atskirus projektus, o ir yra tokiu kuriems dar reikia KDE4... Tenka surinkti viska paciam, nes naudotis KDE4+Qt4+KDE5+Qt5+Gnome+Wayland+Xorg... bent man atrodo kvailyste. Mano budu yra gaunamas visas frameworkas KDE5 (ir tik KDE5!) bei sudiegia keleta utilitu (naudinga naudojant WM ne KDE)

Skriptas netikrina ar sistema turi reikalingas bibliotekas surinkti KDE, o ir palieka dbus skausma nepaliesta (galima paciam copy/paste, arba skaitykit freedesktop dokumentacija kaip leisti dbus servisus is XDG_HOME).

EDIT: Pamirsau run.zsh (reikalingas norint paleisti KDE po non-standard prefix)

T
Techtronic
Mindaugas N.
  • 6 Sau '17

Kartais pravercia:

#!/usr/bin/env perl

sub int2time {
    my $int = shift // return "∞";

    $int = abs int($int);
    $int -= my $s = $int % 60; $int /= 60;
    $int -= my $m = $int % 60; $int /= 60;
    $int -= my $h = $int % 24; $int /= 24;
    $int -= my $d = $int %  7; $int /=  7;
    $int -= my $w = $int;

    my @fmt;
    my @arg;

    if ($w or @arg) { push @fmt, "%dw"; push @arg, $w; }
    if ($d or @arg) { push @fmt, "%dd"; push @arg, $d; }
    if ($h or @arg) { push @fmt, "%dh"; push @arg, $h; }

    push @fmt, "%dm", "%ds";
    push @arg, $m, $s;

    return sprintf("@fmt", @arg);
}

my $str = int2time(shift @ARGV);

print "$str\n";

Veikia taip:

$ skriptas 720 
12m 0s
$ skriptas 7200
2h 0m 0s
$ skriptas 6812247
11w 1d 20h 17m 27s
T
Techtronic
Mindaugas N.
  • 6 Sau '17

Dar keli, galiu testi ir testi nesustodamas (~/.bin/ wc rodo 100+ skriptu) :-).

Kartais tenka siusti/gauti siuntas, kad jas sekti esu parases sau toki skripta:

1

Skriptas:

#!/usr/bin/env perl

use strict;
use warnings;

use LWP::UserAgent;
use HTTP::Cookies;
use JSON::XS;
use Time::Piece;
use Term::ExtendedColor qw(:all);
use open ':std', ':encoding(UTF-8)';

my $code = ($ARGV[0] or 'RO000123456EE');
my $ua = LWP::UserAgent->new;
$ua->cookie_jar(HTTP::Cookies->new(file => "lwpcookies.txt", autosave => 1));
my $req = HTTP::Request->new("POST", "https://track24.ru/ajax/tracking.ajax.php?code=$code");
$req->header(User_Agent => 'Mozilla/5.0 (X11; Linux i686; rv:51.0) Gecko/20100101 Firefox/51.0');
$req->header(Referer => "https://track24.ru/?code=$code");
$req->header(X_Requested_With => "XMLHttpRequest");
$req->content("code=$code&lng=en");
$req->content_type("application/x-www-form-urlencoded");
my $res = $ua->request($req);

die("$res->_msg") if not $res->is_success;

# Work with json now
my $json = decode_json($res->decoded_content);

if ($json->{status} eq "ok") {
    my $first = localtime;
    my $last  = int(0);
    my $now   = localtime;

    printf(
        "# Parcel moving from %s to %s.\n\n",
        fg(131, $json->{data}{fromCountry}),
        fg(134, $json->{data}{destinationCountry})
    );

    foreach my $e (keys %{$json->{data}{groupedEvents}}) {
        printf("%s:\n", fg(68, $e));
        foreach my $i (@{$json->{data}{groupedEvents}{$e}}) {
            my $time = Time::Piece->strptime($i->{operationDateTime}, "%d.%m.%Y %H:%M:%S");

            $first = $time if $time < $first;
            $last  = $time if $time > $last;

            #my $now = localtime;
            #my $diff = $now - $time;

            my $place = $i->{operationPlaceName};
            my $operation = $i->{operationAttribute};
            $operation = "N/A" if $operation eq "";
            $place = "N/A" if $place eq "";
            printf("%s %s: %s %s\n",
                   fg(172, $time->ymd), fg(166, $time->hms),
                   #int($diff->days),
                   fg(60, $place),
                   fg(65, $operation),
            )
        }
        print("\n")
    }

    my $deliveringA = $now - $first;
    my $deliveringB = $now - $last;

    if ($json->{deliveredStat}{averageDeliveryDays}) {
        printf("Delivering %s days average %s (max %s, min %s).\n",
               fg(112, int($deliveringA->days)),
               fg(215, $json->{deliveredStat}{averageDeliveryDays}),
               fg(203, $json->{deliveredStat}{maxDeliveryDays}),
               fg(81, $json->{deliveredStat}{minDeliveryDays}),
        )
    }
    printf("%s: %s %s (%s days ago).\n",
           fg(68, "First seen"),
           fg(172, $first->ymd),
           fg(166, $first->hms),
           fg(215, int($deliveringA->days))
    );
    printf("%s:  %s %s (%s days ago).\n",
           fg(68, "Last seen"),
           fg(172, $last->ymd),
           fg(166, $last->hms),
           fg(215, int($deliveringB->days)),
       );
}

Jeigu tenka susidurti su unicode tai pravercia:

2

Skriptas:

#!/usr/bin/env perl

use utf8;
use strict;
use warnings;

use Encode qw(decode);
use I18N::Langinfo qw(langinfo CODESET); 

use charnames ();
use List::Util;

binmode STDOUT, ':utf8';

my %r = (
    u => qr/(?:U\+?(?<hex>[0-9A-F]+))/i,
    h => qr/(?:0x(?<hex>[0-9A-F]+))/i,
    d => qr/(?:(?<int>[0-9]+))/,
);

my %transformation = (
    'hex' => sub { hex $_[0] },
    'int' => sub { $_[0] },
);

my $codeset = langinfo(CODESET);
@ARGV = map { decode $codeset, $_ } @ARGV;

foreach (@ARGV) {
    print "Processing $_\n";
    my($code, $match);

    if(/ \A (?: $r{u} | $r{h} | $r{d} ) \z /x) {
        $match = 'code point';
        my ($key) = keys %+;
        $code = $transformation{$key}($+{$key});        
    }
    if(/ \A ([A-Z\s]+) \z /ix) {
        $match = 'name';
        $code = charnames::vianame( uc($1) );
    }
    if(/ \A (\X) \z /x) {
        $match = 'grapheme';
        $code = ord( $1 );
    }

    # default {
    #     unless( $code ) {
    #         print "\tInvalid character or codepoint --> $_\n";
    #         next;
    #     }
    #     #continue;
    # }

    my $hex  = sprintf 'U+%04X', $code;
    my $char = chr($code);
    $char = '<unprintable>' if $char !~ /\p{Print}/;
    $char = '<whitespace>'  if $char =~ /\p{Space}/;
    $char = '<control>'     if $char =~ /\p{Control}/;

    my $name = charnames::viacode( $code ) // '<no name found>';

    print <<"HERE";
    match       $match
    code point  $hex
    decimal     $code
    name        $name
    character   $char

HERE
}

Arba convert is decimal i binary arba vice versa

$ skriptas -db 1234
10011010010
$ skriptas -bd 10011010010
1234

Skriptas:

#!/usr/bin/env perl
use strict;
use Getopt::Long;

usage() unless(@ARGV);

our ($opt_d2b, $opt_d2o, $opt_d2h, $opt_hd, $opt_od, $opt_bd, @to_ascii);
GetOptions('db'   =>  \$opt_d2b,
           'do'   =>  \$opt_d2o,
           'dh'   =>  \$opt_d2h,
           'hd'   =>  \$opt_hd,
           'od'   =>  \$opt_od,
           'bd'   =>  \$opt_bd,
           );

my $int = shift;
print convert($int), "\n";

sub convert { 
  my $int = shift;
  return sprintf("%b",$int, $int) if $opt_d2b;
  return sprintf("%o",$int, $int) if $opt_d2o;
  return sprintf("%x",$int, $int) if $opt_d2h;
  return hex($int) if $opt_hd;
  return oct($int) if $opt_od;
  return oct("0b$int") if $opt_bd;
}

sub usage {
  print << "USAGE";
  USAGE: $0 [OPTIONS] integer
    OPTIONS:
      -db decimal to binary
      -do decimal to octal
      -dh decimal to hexadecimal
      -hd hexadecimal to decimal
      -od octal to decimal
      -bd binary to decimal

USAGE
exit(0);
}
S
  • 6 Sau '17

funkcija failų išskleidimui:

extract () 
{ 
    if [ -f $1 ]; then
        case $1 in 
            *.tar.bz2)
                tar xvjf $1
            ;;
            *.tar.gz)
                tar xvzf $1
            ;;
            *.tar.xz)
                tar Jxvf $1
            ;;
            *.bz2)
                bunzip2 $1
            ;;
            *.rar)
                unrar x $1
            ;;
            *.gz)
                gunzip $1
            ;;
            *.tar)
                tar xvf $1
            ;;
            *.tbz2)
                tar xvjf $1
            ;;
            *.tgz)
                tar xvzf $1
            ;;
            *.zip)
                unzip $1
            ;;
            *.Z)
                uncompress $1
            ;;
            *.7z)
                7z x $1
            ;;
            *)
                echo "don't know how to extract '$1'..."
            ;;
        esac;
    else
        echo "'$1' is not a valid file!";
    fi
T
Techtronic
Mindaugas N.
  • 6 Sau '17

@Supoplex 7z palaiko kone viska:

  • Packing / unpacking: 7z, XZ, BZIP2, GZIP, TAR, ZIP and WIM
  • Unpacking only: AR, ARJ, CAB, CHM, CPIO, CramFS, DMG, EXT, FAT, GPT, HFS, IHEX, ISO, LZH, LZMA, MBR, MSI, NSIS, NTFS, QCOW2, RAR, RPM, SquashFS, UDF, UEFI, VDI, VHD, VMDK, WIM, XAR and Z.

Tad gali sutrumpinti iki minimumo:

# Unpack archive
function ex() {
    [[ -n "${1}" && -r "${1}" ]] && { file ${1} && 7z x ${1} }
}

Arba perziureti, be isskleidimo:

# View archive without unpack
function exs() {
    if [[ -f "${1}" ]]; then
        7z l ${1} | grep --invert-match \
        -e 'Path =' -e 'Type =' -e 'Physical Size =' -e 'Listing archive:' \
        -e 'Copyright (c)' -e 'p7zip Version' -e '^--$' \
        | egrep -v "^[[:space:]]*$|^#"
    fi
}

BONUS tiems kas zsh naudoja:

alias -s gz=exs
alias -s tar=exs
alias -s tgz=exs
alias -s zip=exs
alias -s rar=exs
alias -s iso=exs
alias -s deb=exs
alias -s iso=exs
alias -s exe=exs

Dabar kad paziureti kas yra archyve uztenka parasyti jo pavadinima:
i

T
Techtronic
Mindaugas N.
  • 1
  • 6 Sau '17

For fun.

# Feminism.
function woman() {
    [[ -n ${1} && -x /usr/bin/emacs ]] &&  emacs -nw -Q --eval "(woman \"${1}\")"
}
S
  • 1
  • 9 Sau '17

@Techtronic said:

@Supoplex 7z palaiko kone viska:

  • Packing / unpacking: 7z, XZ, BZIP2, GZIP, TAR, ZIP and WIM
  • Unpacking only: AR, ARJ, CAB, CHM, CPIO, CramFS, DMG, EXT, FAT, GPT, HFS, IHEX, ISO, LZH, LZMA, MBR, MSI, NSIS, NTFS, QCOW2, RAR, RPM, SquashFS, UDF, UEFI, VDI, VHD, VMDK, WIM, XAR and Z.

Tad gali sutrumpinti iki minimumo:

# Unpack archive
function ex() {
   [[ -n "${1}" && -r "${1}" ]] && { file ${1} && 7z x ${1} }
}

neveikė su bash'u, tikriausiai dėl { }, taip pataisiau:

[[ -n "${1}" && -r "${1}" ]] && file ${1} && 7z x ${1}
G
  • 9 Sau '17

@Supoplex said:

```bash

Unpack archive

function ex() {
[[ -n "${1}" && -r "${1}" ]] && { file ${1} && 7z x ${1} }

neveikė su bash'u, tikriausiai dėl '{', '}',
taip pataisiau:
[[ -n "${1}" && -r "${1}" ]] && file ${1} && 7z x ${1}

Paprasčiausiai pamiršo kabliataškį uždėt Pataisyta versija:

function ex() {
  [[ -n "${1}" && -r "${1}" ]] && { file ${1} && 7z x ${1}; }
}
T
Techtronic
Mindaugas N.
  • 1
  • 10 Sau '17

@Ghost said:
Paprasčiausiai pamiršo kabliataškį uždėt Pataisyta versija:

Gal ir taip, Zsh komandu grupese semicolon yra lisnas. O kam jis reikalingas Bash ? Tai vadinasi bashismas ;-)