Visualizzazione post con etichetta bash. Mostra tutti i post
Visualizzazione post con etichetta bash. Mostra tutti i post

2014-09-30

Dizionario on-line da bash con curl

La RFC 2229 descrive il protocollo Internet DICT per permettere l'accesso a dizionari in rete.
Un modo molto semplice per accedere è l'utilizzo del comando curl che supporta tale protocollo.

Un esempio con la parola inglese door che viene tradotta in Italiano in porta o uscio:
curl "dict://dict.org/d:door:fd-eng-ita"
restituisce:
220 pan.alephnull.com dictd 1.12.1/rf on Linux 3.14-1-amd64 <auth.mime> <6051747.13047.1412087461@pan.alephnull.com>
250 ok
150 1 definitions retrieved
151 "door" fd-eng-ita "English-Italian FreeDict Dictionary ver. 0.1.1"
door
 porta; uscio
.
250 ok [d/m/c = 1/0/12; 0.000r 0.000u 0.000s]
221 bye [d/m/c = 0/0/0; 0.000r 0.000u 0.000s]

le righe che iniziano con un numero fanno parte del protocollo ed offrono un utilizzo agevolato per il trattamento automatico:
il 220 corrisponde al messaggio di benvenuto da parte del server che indica i suoi riferimenti e le sue caratteristiche.
il 250 seguito da ok rappresenta la presa in carico della richiesta.
il 150 riporta il numero delle definizioni trovate, se non ce ne fossero il codice sarebbe 552.
Per ogni definizione trovate avremo un 151 con l'indicazione della parola cercata, il codice e la descrizione del dizionario in cui è stata trovata
Di seguito alla riga con codice 151 viene riportato il contenuto della definizione che si conclude con una riga contenente solo un punto "."
Al termine delle definizioni trovate di nuovo un codice 250 con eventuali indicazioni dei tempi impiegati per reperire le informazioni.
Il codice 221 rappresenta i saluti da parte del server per la chiusura della connessione.

Altrettanto interessante può essere l'esecuzione di una richiesta senza specificare il dizionario da usare:
curl "dict://dict.org/d:door"
si ottiene il contenuto della definizione door per il Dizionario Inglese Collaborativo Internazionale che rappresenta il dizionario di default del server dict.org.

Per ottenere la lista dei dizionari disponibili in dict.org eseguire:
curl "dict://dict.org/show:db"
in risposta si ottiene un codice 110 con l'indicazione del numero di dizionari presenti e di seguito la lista indicante il codice e la descrizione di ognuno, termina con la solita riga con un solo punto, poi il 250 e il 221 di saluti.

Nella lista ottenuta vorrei che si notasse:
foldoc "The Free On-line Dictionary of Computing (20 July 2014)"
e trovo doveroso il comando:
curl "dict://dict.org/d:linux:foldoc"

Idea presa da http://www.thegeekstuff.com/2012/04/curl-examples/

2014-06-16

Verifica in bash se una variabile è numerica

Oggi una mia necessità era di verificare se una variabile era di tipo numerico ed il valore maggiore o uguale a zero.
Dopo qualche tentativo sono arrivato alla conclusione che il mio modo preferito di eseguire la verifica era:
A=X
B=5
[ $A -ge 0 ] 2>/dev/null && echo Numerico
[ $B -ge 0 ] 2>/dev/null && echo Numerico
l'aggiunta di "2>/dev/null" permette di non ottenere il messaggio di errore "-bash: [: A: integer expression expected"
Il numero deve essere positivo oppure zero, se si vogliono verificare anche i numeri negativi l'allungo un pochino:
[ $A -ge 0 -o $A -le 0 ] 2>/dev/null && echo Numerico
Per una prova più ampia:
for VAR in 0 1 2 3 4 5 50 100 1000 -1 -2 -5 -50 -100 -100 A C 2A 10X X1 X5
do
[ $VAR -ge 0 -o $VAR -le 0 ] 2>/dev/null && echo $VAR num || echo $VAR NON num
done
Il funzionamento si basa sul comando built-in [ della bash  che implementa il comando test di unix, restituisce un valore di ritorno vero/true solo se la condizione è valida e corretta, quindi confrontando numericamente con l'operatore -ge il valore della variabile rispetto allo zero per verificare se è maggiore o uguale si ottiene vero solo se il contenuto della variabile è un numero valido, altrimenti si ottiene falso. Se il contenuto della variabile non fosse un numero valido allora si otterrebbe il messaggio di errore che possiamo sopprimere con 2>/dev/null che lo redirige verso la device virtuale che distrugge tutto quello che riceve, come se fosse un buco nero.

2013-09-05

bash e la pagina di manuale del comando precedente

Mi capita spesso di impartire un comando errato dovuto ad un'opzione errata che mi costringe a consultare la pagina del manuale del comando, quando il nome del comando è breve faccio prima a digitarlo come parametro per il comando man.
Quando il nome del comando è lungo e non trovo a disposizione le configurazioni di "completion" per completare con TAB il nome del comando, ricorro alla sostituzione con history:
man !!:0
questo mi permette di passare a man il parametro 0 (il nome dell'eseguibile) dell'ultimo comando impartito.
Spero che possa risultare utile anche a qualche altro smemorato, buona digitazione! (poca)

2012-12-07

bash e l'aggiornamento delle dimensioni del terminale

Come ho forse accennato in post passati, utilizzo LXDE come desktop environment e bash come interprete di comandi, il tutto dentro varie linux-box con Arch Linux.
Mi capita spesso di aprire una finestra di terminale, attualmente LXTerminal, e lavorare a linea di comando con grande utilizzo delle funzioni di recupero dei comandi precedenti.
A volte, utilizzando Ctrl-R oppure con la freccia verso l'alto per ricercare un comando precedente, mi è capitato che i caratteri venissero disposti male nella riga di comando in modo da rendere impossibile correggere e avere la certezza di sottomettere il comando corretto.
Ho scoperto che non succede sempre, solo quando ho ridimensionato la finestra del terminale, ma non sempre, sapevo che le variabili COLUMNS e LINES contengono le dimensioni in caratteri della finestra di terminale e che vengono aggiornate al momento del ridimensionamento della finestra stessa ed in condizioni normali vengono aggiornate correttamente.
Capita però a volte che non si aggiornino ed ho verificato che non si aggiornano quando la finestra viene ridimensionata durante l'esecuzione di un programma, che sia esso vim, less o qualsiasi altro programma attivo al momento del resize, anche un semplice sleep o una compilazione.
La causa del mancato aggiornamento delle variabili è dovuta al fatto che il programma LXTerminal o similare, manda un segnale SIGWINCH sotto forma di kill al processo attivo al momento del ridimensionamento e non alla shell.
Per ripristinare i corretti valori delle variabili COLUMNS e LINES si può ricorrere a due metodi:
- ridimensionare la finestra nel momento in cui il controllo è tornato alla bash
- mandare il kill corretto alla shell con il comando:
kill -SIGWINCH $$
Per provare eseguire le seguenti operazioni:
- da bash su terminale grafico eseguire e prendere nota dei valori ottenuti con il comando:
echo $COLUMNS $LINES
- eseguire il comando:
sleep 10
- ridimensionare la finestra entro i dieci secondi, prima della ricomparsa del prompt
- rieseguire il comando precedente e se tutto va come ho descritto i valori dovrebbero essere invariati
- eseguire il ridimensionamento oppure il comando:
kill -SIGWINCH $$
- esaminare di nuovo i valori delle variabili che dovrebbero essere aggiornate, sempre che tutto funzioni come ho descritto

AGGIORNAMENTO
senza ricorrere al kill, quandi si è di nuovo al prompt, si può anche ridimensionare di nuovo la finestra, anche di poco. e le variabili vengono reimpostate

2012-03-29

Marziani in rete ed Open SuSE 11.2

Mar 29 09:12:33 pc2kx kernel: [ 1048.245950] martian source 192.168.2.0 from 0.0.0.0, on dev eth0
Mar 29 09:12:33 pc2kx kernel: [ 1048.245970] ll header: ff:ff:ff:ff:ff:ff:00:00:00:00:fe:01:08:00
Mar 29 09:12:34 pc2kx kernel: [ 1048.999644] martian source 192.168.2.0 from 0.0.0.0, on dev eth0
Mar 29 09:12:34 pc2kx kernel: [ 1048.999665] ll header: ff:ff:ff:ff:ff:ff:00:00:00:00:fe:00:08:00
Mar 29 09:12:34 pc2kx kernel: [ 1049.745748] martian source 192.168.2.0 from 0.0.0.0, on dev eth0
Mar 29 09:12:34 pc2kx kernel: [ 1049.745768] ll header: ff:ff:ff:ff:ff:ff:00:00:00:00:fe:01:08:00
Mar 29 09:12:35 pc2kx kernel: [ 1050.499409] martian source 192.168.2.0 from 0.0.0.0, on dev eth0
Mar 29 09:12:35 pc2kx kernel: [ 1050.499429] ll header: ff:ff:ff:ff:ff:ff:00:00:00:00:fe:00:08:00

Quello che precede è quello che mi trovo regolarmente nel file /var/log/messages da un po' di tempo a questa parte della mia macchina Open SuSE 11.2. So che nella rete al quale sono collegato ci possono essere pacchetti poco puliti e poi mi preoccuperò di sollecitare un controllo a chi di dovere. Per il momento non mi preoccupo dell'origine dei pacchetti che generano il log, voglio solo disabilitare la registrazione nel log di sistema, con la frequenza di un paccheto ogni 75 centesimi di secondi il mio log di sistema diventa ingestibile. Dopo un po' di ricerche e la lettura del seguente thread nel forum OpenSUSE ho eseguito il seguente comando:

sysctl -a|grep -i martian | while read L U; do sysctl -w $L=0;done

Adesso non vengono più riportati nel log i pacchetti marziani. Dopo un po' il servizio DHCP client conferma l'indirizzo IP già ottenuto in precedenza e richiama gli script per sistemare le cose necessarie, in pratica non fa niente, solo che rieseguendo lo script di configurazione del firewall reimposta i valori di sysctl appena modificati. Ricorro allora alla modifica del file /etc/sysconfig/network/scripts/dhcpcd-hook, ho aggiunto la seguente funzione:
 
disable_log_martians()
{
        sysctl -a|grep -i martian | while read L U; do sysctl -w $L=0;done
}

e l'ho richiamata con:

disable_log_martians

prima del ;; del case di up) e new) Adesso aspetto, si fa per dire, se cambia di nuovo qualcosa, poi domani al reboot verifico se tutto funziona come sperato.

2012-03-28

Serie di numeri ottali ed esadecimali in bash

Per ottenere una serie di numeri in uno script si può ricorrere alle caratteristiche di espansione messe a disposizione da bash.
Provate:
echo {1..10}
echo {15..-3}
Oggi ho avuto necessità di ottenere i numeri in notazione ottale da 0000 a 0377 e poi gli stessi valori ma in notazione esadecimale, per ottenerli ho realizzato i seguenti codici per l'espansione:
echo 0{0..3}{0..7}{0..7}
echo {{0..9},{A..F}}{{0..9},{A..F}}
Nel post Sequenze di valori con bash ho trattato più approfonditamente l'argomento delle sequenze di valori.

2011-11-01

Conversioni da esadecimale, binario e ottale a decimale in bash

In bash c'è un costrutto sintattico molto utile per eseguire calcoli, è assimilabile al meccanismo di sostituzione delle variabili:
$((7+5))
nella linea di comando verrà sostituito con 12, per visualizzarlo andrà preceduto dal comando echo:
echo $((7+5))
gli operandi delle espressioni possono essere forniti in diverse basi numeriche, i numeri forniti con 0 come prima cifra saranno interpretati come numeri ottali (in base 8), quelli prefissati da 0x come esadecimali (base 16) e quelli che iniziano per le cifre da 1 a 9 come decimali (base 10).
Per ottenere la conversione in decimale da ottale o esadecimale è sufficiente inserire tra le parentesi il numero da convertire prefissandolo come previsto per indicare la base corretta:
$((0x400))
oppure
$((02000))
per ottenere 1024.
Ogni altra base può essere specificata prefissando con la base seguita dal carattere #, ad esempio per esprimere un numero binario:
$((2#100))
$((4#10))
per ottenere 4.
Se si deve eseguire un calcolo con bsi miste si può liberamente indicare ogni numero con la sua propria base secondo la convenzione descritta.

2011-09-08

Bash e correzione di un lungo nome di file

Se con la shell bash capita di aver creato un file con il nome sbagliato si ricorre al comando mv
mv nome-lunghissimo-e-difficile-da-scrivere-corrotto nome-lunghissimo-e-difficile-da-scrivere-corretto
Non a caso ho scelto questi due nomi in cui la differenza consiste di una sola lettera in quanto gli errori di digitazione d solito sono brevi, la potenza della bash permette di utilizzare un metodo alternativo:
mv nome-lunghissimo-e-difficile-da-scrivere-corr{o,e}tto
In questo modo al comando mv vengono passati due nomi, il primo con la lettera o al posto del pezzo con le graffe, il secondo con la e. Non sempre puo' risultare comodo ma in alcun casi l'ho trovato impagabile... essendo poi open source... effettivamente lo e'.

2011-06-29

Sequenze di comandi con la shell

Da sempre la shell Unix ha permesso di impartire sequenze di comandi che avessero qualche correlazione tra di loro, le correlazioni sono molteplici e proverò con questo post a descriverle.
Il primo modo per impartire una serie di comandi è di digitare i comandi uno di seguito all'altro terminando ognuno con ENTER, con la shell interattiva il comando successivo viene eseguito al termine del comando precedente ma non prima di aver premuto il tasto ENTER che lo sottomette. Per evitare il tempo di attesa tra la fine del primo comando e la pressione del tasto ENTER per il successivo si può iniziare a digitare il comando anche prima della comparsa del prompt da parte della shell ma non sempre si riesce ad essere sufficientemente veloci; a tal proposito si possono digitare i comandi separati da punto e virgola ( ; ) e premere ENTER solo alla fine dell'ultimo. In questo modo i comandi verranno eseguiti uno di seguito all'altro senza attese. Esempio per consultare l'orario prima e dopo l'esecuzione di una copia di directory:
date ; cp -a src_dir dst_dir ; date
L'esecuzione dei comandi successivi può essere condizionata in base all'esito del precedente: separando con && due comandi si condiziona l'esecuzione del secondo in base all'esito del primo, se il primo si conclude positivamente allora viene eseguito anche il secondo. Ricordo che per esito positivo si intende che l'exit code del programma deve essere 0 ( zero ), l'exit code di un programma può essere verificato con la shell utilizzando la variabile predefinita $? . La sequenza di comandi può essere lunga a piacere. Esempio di comando condizionato dal precedente, se la compilazione si completa positivamente si può eseguire il programma:
cc -o prova prova.c && ./prova

Il condizionamento di esecuzione può essere anche invertito con || in modo tale da eseguire il secondo solo se il primo è fallito ( quindi exit code diverso da zero ). Esempio di comando alternativo eseguendo telnet se ssh fallisce, si sa che è preferibile ssh a telnet ma in sua assenza...:
ssh server || telnet ssh
I programmi possono essere eseguiti anche contemporaneamente separandoli con & che permette di eseguire il secondo appena iniziata l'esecuzione del primo, senza attenderne la fine. Esempio di esecuzione contemporanea di cancellazione di un file grande e la copia di un altro:
rm /tmp/grande_file & cp /tmp/altro_file /altrove/altro_file
Terminando con & l'ultimo ( o l'unico ) comando si ottiene di nuovo il prompt appena avviato il comando in modo da poter interagire subito di nuovo con la shell.
Un altro modo molto utilizzato per definire una sequenza di comandi è quello che redirige l'output ( che normalmente finirebbe sullo schermo ) come input ( normalmente la tastiera ) del comando seguente, per fare ciò si separano i due comandi con | ed i due programmi verranno eseguiti contemporaneamente con il sistema operativo che passa i dati in uscita dal primo nell'ingresso del secondo. Esempio di calcolo di occupazione di spazio su disco dei file o directory in ordine crescente di occupazione:
du -s * | sort -n

2011-06-23

Correzione comando precedente in bash

Nel post precedente Esecuzione del comando precedente con sudo in bash ho esposto un tipo di utilizzo della history delle shell con particolari riferimenti a bash, la tecnica esposta utilizza la scorciatoia !! che corrisponde al comando precedente.

Questa volta il comando precedente andrà modificato per essere eseguito con qualche correzione, il caso più frequente che mi si presenta è quello in cui devo verificare il contenuto di un tarball ( un archivio in formato tar di solito compresso con gzip o bzip2 ) e poi estrarne il contenuto.

2011-05-17

Sequenze di valori con bash

Negli script serve a volte una serie di numeri o caratteri in sequenza e bash prevede la funzionalità per generarli agevolmente.
Si utilizza quella che viene definita Brace Expansion e per ottenere una lista di numeri da 1 a 7 il formalismo previsto è {1..7} , i numeri 1 e 7, separati da una coppia di punti, rappresentano il numero iniziale e quello finale, quindi provando ad eseguire:
echo {1..7}
si ottiene
1 2 3 4 5 6 7
qualsiasi comando al posto di echo otterrà gli stessi valori come parametro quindi con il comando
touch file{1.20}.txt
otterremo venti file vuoti con i nomi "file1.txt", "file2.txt" e così via fino a file20.txt.

2011-05-05

Esecuzione del comando precedente con sudo in bash

Se vi capita spesso di amministrare un sistema Unix/Linux e, come è giusto, non avete effettuato il login come root, potrebbe succedervi, come succede a me, di dimenticare di aggiungere sudo prima di un comando che necessita dei permessi di superuser, in questo caso l'operazione più noiosa sarebbe quella di scrivere un nuovo comando iniziando con sudo e poi riscrivere interamente il comando precedente, spero per voi che non facciate in questo modo, ci sono metodi un po' più veloci, se il comando da ripetere è breve potrebbe essere accettabile ma molti comandi sono lunghi, complessi e nascondo insidie da evitare.