Φανουργάκης Μανώλης(mailto:mfano@NOSPAMfreemail.gr) Αυγ 2003
Μερικά tips που διευκολύνουν τη ζωή μας στη γραμμή εντολής
1. Aliases
2. Shell prompt
3. Vi (=very intelligent) editor
4. Screen
Τα παρακάτω aliases μπορούν να μπουν στο ~/.bashrc. Αν όμως γίνουν πολλά, είναι καλύτερα για λόγους τάξης να μπουν σε ένα ξεχωριστό αρχείο, π.χ. στο ~/.alias και να μπει στο ~/.bashrc η γραμμή:
test -s ~/.alias && . ~/.alias
alias l='ls -lA ' alias lh='l -h '
Ο διακόπτης -h της ls είναι αρκετά χρήσιμος γιατί μετατρέπει το μέγεθος αρχείων σε kB,MB,GB. Έτσι, με 'l ~/mbox' θα πάρω το παρακάτω:
-rw------- 1 manolis users 135987 Ιούλ 28 22:33 /home/manolis/mbox
Ενώ με 'lh ~/mbox' το παρακάτω:
-rw------- 1 manolis users 133k Ιούλ 28 22:33 /home/manolis/mbox
alias m='$PAGER'
Όπου η μεταβλητή PAGER έχει τεθεί στο ~/.bashrc ως εξής:
export PAGER='less -rM '
Ή ό,τι άλλο χρησιμοποιείται ως pager τέλος πάντων. Εξαιρετικά βολικό, χρησιμοποιώ το less αμέτρητες φορές κάθε μέρα.
alias pd='pushd' alias po='popd' alias ds='dirs -v'
Χρήσιμα για τις ...περιπλανήσεις μας στη δομή αρχείων του linux.
Οι εντολές pushd, popd, dirs χειρίζονται μια στοίβα (stack) καταλόγων στους οποίους μετακινούμαστε.
Ένα παράδειγμα θα γίνει πιο εύκολα κατανοητό:
$ pd /tmp/ /tmp ~
Ξεκινώντας ένα νέο shell βρίσκομαι στο home directory. Κάνω push το /tmp. Παρατηρώ ότι η pushd μου αναφέρει και την κατάσταση της στοίβας: Στην κορφή βρίσκεται το /tmp και μετά το home από όπου ξεκίνησα.
$ pd /usr/local/bin/ /usr/local/bin /tmp ~
Έκανα push και το /usr/local/bin. Η στοίβα τώρα έχει τρεις καταλόγους.
$ ds 0 /usr/local/bin 1 /tmp 2 ~
Ας υποθέσουμε τώρα ότι θέλω να εναλλάσομαι γρήγορα μεταξύ αυτών των καταλόγων. Με ένα pushd +n (όταν χρησιμοποιήσουμε την pushd χωρίς όρισμα, εννοείται +1) ο κατάλογος που βρίσκεται στη θέση n πάει στην κορυφή.
$ pd +1 /tmp /usr/local/bin ~
Με ένα popd ξεφορτώνομαι τον κατάλογο που βρίσκεται στην κορυφή και μεταφέρομαι στον αμέσως επόμενο.
$ po /usr/local/bin ~
Με τη σωστή χρήση των pushd, popd, dirs μπορούμε να κάνουμε πολύ γρήγορα πολύπλοκες δουλειές. Και μην ξεχνάτε ότι τα πλήρη ονόματα των καταλόγων μπορεί να γίνουν πολύ μεγάλα (π.χ. /usr/X11R6/lib/X11/fonts/hellas/, ~/download/pictures/flags/greece/). Είναι πολύ βολικό να μπορεί κανείς με τρία χτυπήματα πλήκτρων να εναλάσσεται μεταξύ τους.
Για περισσότερες πληροφορίες 'help pushd', 'help popd', 'help dirs'.
Επίσης, ας μην ξεχνάμε και την εντολή 'cd -' που μας τοποθετεί στον προηγούμενο κατάλογο (σ' αυτόν που είμασταν πριν κάνουμε cd ή pushd/popd).
alias pt='echo $PATH|tr : \\n ' addpath() { while test "$1" ; do PATH=${PATH}:"$1" ; shift ; done ; }
Το alias pt κάνει το εξής απλό και έξυπνο: Παίρνει τη μεταβλητή PATH και την περνάει στην εντολή tr (δώστε man tr) ώστε να μετατρέψει τις άνω και κάτω τελείες που χωρίζουν τους καταλόγους του path σε αλλαγές γραμμών. Έτσι έχουμε το εξής ευανάγνωστο αποτέλεσμα:
$ pt /usr/local/bin /usr/bin /usr/X11R6/bin /bin /usr/games/bin /opt/gnome/bin /opt/kde3/bin .
Η συνάρτηση addpath προσθέτει τα ορίσματά της στο τέλος της μεταβλητής PATH. Οι συναρτήσεις (functions) του shell είναι σαν μικρά σκριπτάκια, έχουν πιο πολλές δυνατότητες από τα απλά aliases. Εδώ όπως βλέπετε μπορούμε να χειριστούμε μία- μία όλες της παραμέτρους της addpath().
(Για περισσότερες πληροφορίες, man bash, section FUNCTIONS)
Το shell μας δίνει τη δυνατότητα να επαναλάβουμε μια προηγούμενη εντολή χωρίς να χρειάζεται να την πληκτρολογήσουμε ολόκληρη.
(Για περισσότερες πληροφορίες, man bash, section HISTORY)
export FIN='-printf %s\t%TY-%Tm-%Td-%TX\t%p\n'
Έχοντας αυτή τη γραμμή στο ~/.bashrc έχω πάντα στο shell μου μια μεταβλητή, την FIN. Το κείμενο της είναι μια εντολή μορφοποίησης για τα αποτελέσματα της find. Δίνοντας λοιπόν "find dir $FIN" παίρνω μια λίστα των αρχείων κάτω από τον κατάλογο dir στην εξής μορφή:
135987 2003-07-28-22:33:13 ./mbox
Στην πρώτη στήλη το μέγεθος του αρχείου, στη δεύτερη η ημερομηνία τροποποίησης και στην τρίτη το όνομα του αρχείου. Οι στήλες είναι χωρισμένες με tab.
Κατευθύνοντας τώρα την έξοδο της προηγούμενης εντολής στην sort μπορούμε να κάνουμε πολύ ενδιαφέροντα πράγματα:
% find $FIN |sort -rnk 1|head -n 4 5146003 2003-08-02-20:45:48 ./Mail/LGU 2457441 2003-08-01-11:00:07 ./Mail/saved 2029849 2003-02-04-20:32:24 ./tmp/lp/ss11 1603828 2003-07-28-22:22:08 ./downl/wg/glib-2.2.2.tar.bz2
Ο διακόπτης '-k NUM' της sort κάνει ταξινόμηση σύμφωνα με το NUM-οστό πεδίο. Εδώ βάλαμε το πρώτο, το μέγεθος δηλαδή. Το 'r' είναι για φθίνουσα ταξινόμηση. Το 'n' είναι για να λάβει η sort υπόψη της ότι πρόκειται για αριθμούς (και να μη βάλει το 11111 πριν από το 11 στη φθίνουσα ταξινόμηση, για παράδειγμα). Χρησιμοποίησα το φίλτρο head για να κρατήσω τις πρώτες 4 γραμμές μόνο (man head).
Τι κάναμε δηλαδή; Κάναμε μια αναζήτηση κάτω από τον τρέχοντα κατάλογο και βρήκαμε τα πιο μεγάλα σε μέγεθος αρχεία.
Άλλο:
% find $FIN |sort -rk 2|head -n 4 20480 2003-08-03-12:32:13 ./tmp/.tips.swp 7946 2003-08-03-12:32:13 ./tmp/tips 4096 2003-08-03-12:32:13 ./tmp 150606 2003-08-03-12:21:35 ./.bash_history
Κάναμε ταξινόμηση ως προς την ημερομηνία και ώρα τροποποίησης.
Παρατήρηση: Η find μας επιστρέφει και ονόματα καταλόγων (όπως το ./tmp που φαίνεται πιο πάνω). Για να μην το κάνει αυτό μπορούμε να προσθέσουμε στις παραμέτρους της find το '! -type d'.
(man find για περισσότερες πληροφορίες).
Αυτό που κάναμε για την find μπορούμε να το κάνουμε και για άλλες εντολές όταν υπάρχει ένα αρκετά μακρύ command line που πληκτρολογούμε συχνά. Να μπαίνει δηλαδή ένα κομμάτι της εντολής που είναι πάντα σταθερό σε μια μεταβλητή του shell ή αν είναι όλη η εντολή σταθερή να μπαίνει όλη σε ένα alias.
Για παράδειγμα, κάθε φορά που διαβάζω ένα ενδιαφέρον ρητό πάω και το προσθέτω σε ένα αρχείο των fortunes. Με τα παρακάτω γλυτώνω πολλή πληκτρολόγηση:
alias addfort='pushd /usr/local/share/games/fortunes;vi quotes;strfile quotes;popd'
Για το rip ενός dvd:
alias dvdrip='for i in `seq 1 $n` ; do mplayer -dvd $i -dumpstream -dumpfile ${i}.stream ; done'
Αφού πρώτα θέσουμε τον αριθμό τίτλων του dvd, τους κάνουμε όλους rip με μια εντολή:
% n=3;dvdrip
Το παραπάνω μπορούσε να γίνει πιο απλά με μια συνάρτηση:
dvdrip() { for i in `seq 1 $1` ; do mplayer -dvd $i -dumpstream -dumpfile ${i}.stream ; done ;}
οπότε θα χρειαζόταν απλά:
% dvdrip 3
alias h='history ' alias he='head ' alias t='tail ' alias j='jobs -l '
Γλυτώνουμε πληκτρολόγηση...
alias ejclcd='eject /dev/cdrom;sleep 5s;eject -t /dev/cdrom'
Γιατί να πρέπει να κουραζόμαστε να πατάμε το κουμπί του cd όταν μπορεί να το κάνει το λινουξάκι για μας ;-) ejclcd, βγαίνει το πορτάκι, βάζουμε το δισκάκι, κλείνει μόνο του.
ssdu() { ls -AQ|xargs du -sb|sort -rn|cut -f 2|awk '{print """ $0 """}'|xargs du -sh ; } ssdus() { while test "$1";do du -sb "$1";shift;done|sort -rn|cut -f 2|awk '{print """ $0 """}'|xargs du -sh ; }
Να κάτι πιο εξεζητημένο: Η ssdu δείχνει, σε φθίνουσα σειρά, πόσο χώρο χρησιμοποιεί, σε kB/MB/GB, κάθε στοιχείο (αρχείο ή κατάλογος) του τρέχοντος καταλόγου. Και αν θέλετε για συγκεκριμένα αρχεία/καταλόγους μονο, η ssdus παίρνει και ορίσματα.
Βασική ιδέα είναι να τρέξει πρώτα η du για να μας δώσει λίστα αρχείων και καταλόγων ταξινομημένων κατά μέγεθος. Στη συνέχεια για κάθε στοιχείο της λίστας, παίρνουμε το όνομα και δείχνουμε μαζί και το μέγεθός του σε kB/MB/GB.
Το command prompt του shell μπορεί να μας παρέχει σημαντικές πληροφορίες. Π.χ. βάζοντας στο ~/.bashrc τη γραμμή:
export PS1='\u \w (\#)% '
θα πάρουμε ένα prompt του τύπου:
manolis /usr/local/bin (15)%
που μας δείχνει το όνομα του χρήστη, τον τρέχοντα κατάλογο και τον αριθμό των εντολών που έχουμε πληκτρολογήσει. (Ο αριθμός αυτός είναι χρήσιμος για την εντολή history[1]).
Το shell μας δίνει τη δυνατότητα να εμφανίσουμε στο prompt ένα σωρό χρήσιμα πράγματα, όπως το hostname (/h), τον αριθμό των εργασιών που τρέχουν στο υπόβαθρο (/j), την ημερομηνία και ώρα (/d, /t). Φυσικά πρέπει να επιλέξει κανείς μόνο όσα πραγματικά είναι χρήσιμα γιατί ένα πολύ μακρύ prompt δυσχεραίνει τη χρήση του τερματικού.
Μπορούμε να τρέξουμε ακόμα και ένα πρόγραμμα και να δείξουμε την έξοδό του στο prompt. Δώστε "PS1='`uptime` % '" χωρίς τα εισαγωγικά. Δοκιμάστε επίσης "PS1='\n`fortune`\n $ '" Κάπως περίεργο, αλλά έχει πλάκα. 8-)
Για περισσότερες πληροφορίες, man bash, section PROMPTING.
Κατ' αρχάς διαβάστε τα tips που δίνονται στα τεύχη 22 και 27 του magaz.
Έχω βάλει στο ~/.vimrc μου τα εξής:
map <F1> :w<CR> map <F2> j. map <F5> :bp<CR> map <F6> :bn<CR> map <F7> :files<CR> map <F8> :bdelete<CR>
Κάνουμε map:
Επίσης,
Για περισσότερα για κάθε εντολή, 'help command' μέσα στο περιβάλλον του vi.
Η screen είναι ένα πολύ χρήσιμο πρόγραμμα που μας δίνει τη δυνατότητα να έχουμε σε ένα τερματικό πολλές οθόνες.
Τρέχουμε τη screen και φαίνεται να μας ανοίγει ένα νέο shell. Πατώντας 'Ctrl-A w' (Control και A μαζί και στη συνέχεια τα αφήνουμε και πατάμε w) φαίνονται οι οθόνες που έχουμε. Στην προκειμένη είναι μόνο μία: η νούμερο 0 με τίτλο 'bash'. Μπορούμε να διορθώσουμε τον τίτλο πατώντας 'Ctrl-A A'.
Πατώντας 'Ctrl-A c' φτιάχνουμε μια καινούρια οθόνη. Άλλος τρόπος έιναι δίνοντας screen (όταν βρισκόμαστε ήδη μέσα στη screen, φτιάχνει μια καινούρια οθόνη, δεν τρέχει νέο στιγμιότυπο της screen). Μπορούμε με 'screen -t title' να της δώσουμε και τίτλο.
Ο πιο απλός τρόπος να τερματίσουμε μια οθόνη είναι να κάνουμε logout από το shell της.
Με 'Ctrl-A n' μεταφερόμαστε στην οθόνη με αριθμό n. Με 'Ctrl-A Ctrl-A' εναλλασόμαστε μεταξύ της τρέχουσας και της προηγούμενης οθόνης.
Φτιάχνοντας ένα αρχείο ~/.screenrc και προσθέτοντας την παρακάτω γραμμή
caption always "[%n %t]%? (%W)%? (%D %d %M,%c) (%l)"
λέμε στη screen να μας δείχνει στο κάτω μέρος της οθόνης μας τις εξής πληροφορίες:
[0 main] (1 kernel-build) (Sun 03 Aug,13:44) (1.17 1.11 1.04)
Με τη screen μπορούμε να το παίζουμε ... σε πολλά ταμπλώ έχοντας μόνο ένα τερματικό ανοιχτό.
Επίσης, άλλη πολύ ενδιαφέρουσα δυνατότητα της screen είναι ότι μπορεί να χωρίσει την οθόνη σε πολλά οριζόντια τμήματα. Σε κάθε ένα από αυτά θα αντιστοιχεί μια οθόνη, με δυνατότητα ρύθμισης φυσικά του ύψους του καθενός.
Τέλος, με τη screen έχουμε τη δυνατότητα να κάνουμε detach και reattach ένα session.
Με (Ctrl-A d) γίνεται το detach, οπότε κλείνει η screen. Το session μας όμως δεν χάθηκε. Δίνοντας screen -ls θα πάρουμε μια έξοδο της μορφής:
There are screens on: 781.pts-0.linux (Attached) 893.pts-3.linux (Attached) 2002.pts-7.linux (Detached) 3 Sockets in /tmp/uscreens/S-manolis.
Με 'screen -r 2002' (το pid δεν χρειάζεται όταν υπάρχει μόνο ένα detached session) ξανακάνουμε attach το session στο τρέχον τερματικό συνεχίζοντας τη δουλειά μας ακριβως απο εκεί που την αφήσαμε)
Αν το session δεν είναι detached και δεν έχουμε, για κάποιο λόγο, πρόσβαση σ' αυτό μπορούμε να χρησιμοποιήσουμε την εντολή 'screen -d -r pid' η οποία κάνει πρώτα detach κι ύστερα attach στο τρέχον τερματικό.
Μια περίπτωση στην οποία αυτή η ιδιότητα είναι πολύ χρήσιμη είναι σε remote shells. Ας υποθέσουμε ότι συνδέόμαι με telnet σε ένα απομακρυσμένο unix box και αρχίζω να κάνω μια δουλειά. Μπορώ ανά πάσα στιγμή να κάνώ detach και να τερματίσώ τη σύνδεση. Όταν αργότερα ξανασυνδεθώ, κάνω attach το προηγούμενο session και συνεχίζω τη δουλειά μου από εκεί που την άφησα!