Difference between revisions of "Bash Tips"

From YobiWiki
Jump to navigation Jump to search
 
(22 intermediate revisions by 2 users not shown)
Line 78: Line 78:
 
** Registering a custom function to complete command line of e.g. myprog: complete -F _myprog -o dirnames myprog
 
** Registering a custom function to complete command line of e.g. myprog: complete -F _myprog -o dirnames myprog
 
** Creating the custom function:
 
** Creating the custom function:
  +
<source lang=bash>
 
_myprog()
 
_myprog()
 
{
 
{
Line 86: Line 87:
 
return 0
 
return 0
 
}
 
}
  +
</source>
 
 
==Misc==
 
==Misc==
   
Line 113: Line 114:
   
 
What is the output of this command?
 
What is the output of this command?
  +
<source lang=bash>
<pre>
 
 
echo one>/tmp/t;(echo two>/dev/stdout)>>/tmp/t;cat /tmp/t
 
echo one>/tmp/t;(echo two>/dev/stdout)>>/tmp/t;cat /tmp/t
</pre>
+
</source>
   
 
Now, try...
 
Now, try...
Line 132: Line 133:
 
To constitute a dictionary for Scrabble from a french dict:
 
To constitute a dictionary for Scrabble from a french dict:
 
grep -v [-\'.] /usr/share/dict/french|unaccent ISO-8859-1|sort -u>scrabble-french
 
grep -v [-\'.] /usr/share/dict/french|unaccent ISO-8859-1|sort -u>scrabble-french
  +
Usual prefixes:
  +
cat scrabble-french |cut -c-3|uniq -c|sort -n -r|gawk '$1>1000{print $2}'
  +
cat scrabble-french |cut -c-2|uniq -c|sort -n -r|gawk '$1>2000{print $2}'
 
To find usual suffixes, invert the dictionary:
 
To find usual suffixes, invert the dictionary:
 
cat scrabble-french|tr "\n" "."|tac -r -s.|tr "." "\n"|sort>scrabble-suffix
 
cat scrabble-french|tr "\n" "."|tac -r -s.|tr "." "\n"|sort>scrabble-suffix
  +
Then find the most common suffixes:
  +
cat scrabble-suffix |cut -c-4|uniq -c|sort -n|gawk '$1>1000{print $2}'|tr "\n" "."|tac -r -s.|tr "." "\n"
  +
cat scrabble-suffix |cut -c-3|uniq -c|sort -n|gawk '$1>2000{print $2}'|tr "\n" "."|tac -r -s.|tr "." "\n"
  +
cat scrabble-suffix |cut -c-2|uniq -c|sort -n|gawk '$1>2000{print $2}'|tr "\n" "."|tac -r -s.|tr "." "\n"
  +
cat scrabble-suffix |cut -c-1|uniq -c|sort -n|gawk '$1>5000{print $2}'|tr "\n" "."|tac -r -s.|tr "." "\n"
  +
===History===
  +
To enable timestamps in the history, set the env variable (see 'man strftime')
  +
HISTTIMEFORMAT='%F %T '
  +
To convert timestamps from the history file
  +
perl -e 'print scalar localtime(1141863326), "\n"'
  +
To keep the history "forever", here is a nice [http://www.onerussian.com/Linux/.files/.bashrc_history .bashrc_history] script to install
  +
<br>I adapted some stuff:
  +
* Enable timestamps on individual commands
  +
* Dates expressed as YY-MM-DD hh:mm:ss
  +
* Converted copy of the individual timestamps (requires gawk so enable it only if you have gawk, this is purely cosmetic as timestamps can be converted later if needed)
  +
* Trap HUP also as invoked bash from mc is apparently interrupted this way
  +
<source lang=diff>
  +
if [ "$PS1" ] ; then # interactive shell
  +
- export STARTTIME=`date` \
  +
- HISTORYDUMP=0
  +
+ export STARTTIME=`date '+%Y-%m-%d %H:%M:%S'` \
  +
+ HISTORYDUMP=0 \
  +
+ HISTTIMEFORMAT='%F %T '
  +
shopt -s cmdhist histappend
  +
  +
# Next function really stores the history logs. Besides that if you want to store whatever you have so far
  +
# you can call this function and it will save increment from the last call to it.
  +
archive_history()
  +
{
  +
TFILE=${HISTFILE}.$$.temp
  +
- CURTIME=`date`
  +
+ CURTIME=`date '+%Y-%m-%d %H:%M:%S'`
  +
CURTTY=`tty`
  +
#STAMP
  +
HISTORYDUMP=$(($HISTORYDUMP+1))
  +
# Title
  +
echo "#$USER@${HOSTNAME} [ ${STARTTIME} - ${CURTIME} ]:$HISTORYDUMP ($CURTTY) ----" >| $TFILE
  +
# Fresh tasty history
  +
history -a ${TFILE}
  +
# Append it to the archive
  +
- cat ${TFILE} >> ${HISTFILE}.archive
  +
+ #cat ${TFILE} >> ${HISTFILE}.archive
  +
+ # But we add a converted version of the timestamp
  +
+ gawk '/^#[0-9]+$/{print strftime("#%F %T ", gensub(/#/,"","g")) }//' ${TFILE} >> ${HISTFILE}.archive
  +
# Adjust history file itself
  +
# of cause we need to dump to some temp file and then rename... he heh
  +
cat ${HISTFILE} ${TFILE} | tail -${HISTSIZE} >| ${HISTFILE}.$$
  +
mv -f ${HISTFILE}.$$ ${HISTFILE}
  +
# clean up after yourself - to be absessive remove the other tmp file as well -
  +
# - might happen if there were no permission to move it at above point
  +
rm -rf ${TFILE} ${HISTFILE}.$$
  +
}
  +
  +
- trap 'archive_history' EXIT
  +
+ trap 'archive_history' EXIT HUP
  +
unset IGNOREEOF
  +
  +
fi
  +
</source>
  +
And to install the script it is better to insert the following in ~/.bashrc
  +
source ~/.bashrc_history
  +
because e.g. with "vserver xxx enter" the shell is not started in the homedir
  +
<br>['''UPDATE'''] now this "patch" is included in the upstream version, thanks Yaroslav!
  +
<br>Another nice tip from Yaroslav is to define another function in .bashrc_history:
  +
gbha () { grep "$@" ~/.bash_history.archive; }
  +
so you just type "gbha PATTERN" (gbha = grep bash history archive) to find what you need!
  +
====Examples====
  +
What did I install last?
  +
gbha "^apt-get install"|tail
  +
When did I modified syslog.conf?
  +
gbha -B2 "syslog.conf"
  +
What did I do that day between 10:00 and 11:59?
  +
gbha -E -A2 "#2006-12-09 1[01]:"
  +
== Conversion d'une string hex en texte ==
  +
  +
Input: 48656c6c6f20776f726c640a <br />Output:Hello world
  +
  +
  +
echo "48656c6c6f20776f726c640a" |\
  +
gawk 'BEGIN{FS=""};{for(i=1;i&lt;=NF;i+=2)printf("%c",strtonum("0x"$i$(i+1)))}'
  +
  +
In Perl:
  +
  +
  +
my $str = "02000501524550454154434f44453a323530";
  +
print pack('C*', map { hex } unpack('(A2)*', $str));
  +
==Compter en hex==
  +
for ((i=0;i<65536;i++)) ; do f=$(printf "%0*X\n" 4 $i); echo $f;done
  +
==Fix sshd under Cygwin==
  +
Symptom: After IT policy...?? Can connect to sshd but visibly server cannot spawn to user shell
  +
<br>Fix
  +
cygrunsrv -E sshd
  +
cygrunsrv -R sshd
  +
rm -rf /var/log/sshd* /etc/ssh_host* /etc/sshd_config /var/empty /tmp/ssh*
  +
net user cyg_server /delete
  +
net user sshd /delete
  +
sed -i '/^cyg_server/d;/^sshd/d' /etc/passwd
  +
ssh-host-config -y
  +
ssh-user-config
  +
cygrunsrv -S sshd
  +
Note that "-d" debug option of ssh-host-config seems to interfere and installation fails if used.
  +
  +
Still troubleshooting new version...
  +
* delete privileged accounts (net user cyg_server /delete...)
  +
* fix? /usr/share/csih/cygwin-service-installation-helper.sh :
  +
2990: #if ! passwd -e "${csih_PRIVILEGED_USERNAME}" >/dev/null
  +
2991- if ! passwd -e "${csih_PRIVILEGED_USERWINNAME}" >/dev/null
  +
* see above, do it manually (ssh-host-config #-y) and change proposed DOMAINNAME+cyg_server privileged account in simpler "cyg" (otherwise apparently it's too long for passwd)
  +
* ? in /etc/fstab add "noacl":
  +
none /cygdrive cygdrive binary,noacl,posix=0,user 0 0
  +
  +
==Create quickly an empty file==
  +
Want to create e.g. a big file for a loop filesystem?
  +
<br>dd is way too slow
  +
<br>To allocate space (on filesystems supporting it, FAT doesn't)
  +
fallocate -l 50G mystuff.img
  +
Else, working on FAT:
  +
truncate -s 50G mystuff.img
  +
Then e.g.
  +
/sbin/mkfs.ext3 mystuff.img
  +
mkdir mystuff.mnt
  +
sudo mount -o loop mystuff.img mystuff.mnt
  +
  +
==DON'T TRY AT HOME==
  +
:(){ :|:& };:

Latest revision as of 17:56, 24 February 2015

Documentation

Sous MC

Shortcuts

  • ctrl+o: toggler l'affichage console/mc
  • alt+o: même chemin dans l'autre fenêtre
  • alt+enter: copie sur la ligne de commande le nom du fichier pointé
  • * (num key!): inverse la sélection
  • + (num key!): permet de sélectionner selon un filtre, par défaut prend directement tous les fichiers (pas les réps) dans le répertoire courant
  • - (num key!): permet de désélectionner avec un filtre
  • ctrl+u: undo
  • ctrl+l: rafraîchir l'écran
  • Bien plus dans le manuel: F1 -> appuyer sur down pour aller sur "contents"; enter -> les keys

Tips

  • Pour pouvoir faire des sélections à la souris (gpm ou X) sans que mc ne les interprète, tenir la touche shift enfoncée
  • J'aime lancer mes mc root avec un alias qui me met un fond rouge plutot que bleu, l'idée vient de Damn Small Linux mais ici en employant les options mc:
alias smc='sudo -H mc --colors normal=,red:selected=,brightmagenta:marked=,red:markselect=,brightmagenta:directory=,red:executable=,red:link=,red:stalelink=brightcyan,red:device=,red:special=,red:core=,red:input=,green /root'
  • mc permet de se connecter via ftp ou ssh, d'ouvrir les tar.gz, tar.bz2, les rpm, les deb, les iso, ... en fait quasi tout ce qui peut être représenté comme un système de fichiers, réel ou virtuel.
  • Si il y a un problème avec la touche alt (qui ne fonctionne pas en tant que touche "meta"): F9 -> options -> display bits -> 3eme: uncheck full 8-bits input
    Cela mettera use_8th_bit_as_meta=1 dans ~/.mc/ini
  • Pour d'autres problèmes de ce type, jetez un oeil à cette FAQ

Séquences de couleur ISO 6429 (ANSI)

echo -e "Test \033[31mrouge\033[m"
echo -e "Test \033[1;31mrouge vif\033[m"
echo -e "Test \033[32mvert\033[m"
echo -e "Test \033[1;31mvert vif\033[m"
man dir_colors
ESC[rowsA          Cursor up
ESC[rowsB          Cursor down
ESC[colsC          Cursor right
ESC[colsD          Cursor left
ESC[row;colH       Set cursor position (top left is row 1, column 1)
ESC[2J             Clear screen
ESC[K              Clear from cursor to end of line
ESC[row;colf       Set cursor position, same as "H" command
ESC[=modeh         Set display mode; see table of mode values below
ESC[=model         Set display mode; see table of mode values below
ESC[attr;attr;..m  Set display attributes; see table of attribute values below
ESC[key;string;..p Substitute "string" for the specified key; see key substitutions section below.
ESC[s              Save cursor position (may not be nested)
ESC[u              Restore cursor position after a save

Attribute Description

  • 0 All attributes off (normal white on black)
  • 1 High intensity (bold)
  • 2 Normal intensity
  • 4 Underline (usually effective only on monochrome displays)
  • 5 Blinking
  • 7 Reverse Video
  • 8 Invisible
  • 30-37 Set the foreground color: 30=Black 31=Red 32=Green 33=Yellow 34=Blue 35=Magenta 36=Cyan 37=White
  • 40-47 Set the background color: 40=Black 41=Red 42=Green 43=Yellow 44=Blue 45=Magenta 46=Cyan 47=White

Settings are cumulative, so (for example) to set bright red foreground set all attributes off, then set red, then bold: echo _[0;31;1m.

Display Modes

  • 0 Text 40x25 monochrome
  • 1 Text 40x25 color
  • 2 Text 80x25 monochrome
  • 3 Text 80x25 color
  • 4 Graphics 320x200 4-color
  • 5 Graphics 320x200 4-color
  • 6 Graphics 640x200 2-color
  • 7 (cursor wrap kludge)

Mode 7 is an unfortunate kludge; Setting mode 7 with an "h" command tells ANSI to wrap text to the next line when it passes the end of a line; setting mode 7 with an "l" (lower-case L) command tells ANSI not to wrap text. For all other modes the "h" and "l" commands are equivalent.

Key Substitutions

The key substitutions ("p") command causes ANSI to substitute the text in "string" when the specified key is pressed. The key code can be a single character in quotes, a numeric ASCII value, or an extended code for a non ASCII key (e.g. function or cursor keys) in the form 0;n, where n is the scan code for the key. The string to be substituted can be a single character or character string in quotes, a numeric ASCII value, or an extended key code.
For a list of numeric ASCII values, see ASCII Tables. For a list of extended key codes see Key Code and Scan Code Tables.
To clear a key substitution, "substitute" the original key for itself.

TAB completion

  • Avoid the bell: add "set bell-style visible" to ~/.inputrc (versus audible and none)
  • Discover the rules when completing a given command, e.g. acroread: complete|grep acroread


Rules are in /etc/bash_completion and loaded in the environment (see set)

  • See http://aplawrence.com/Unix/customtab.html
    • Enabling custom completions: shopt -s progcomp
    • Registering a custom function to complete command line of e.g. myprog: complete -F _myprog -o dirnames myprog
    • Creating the custom function:
 _myprog()
 {
    local curw
    COMPREPLY=()
    curw=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=($(compgen -A user -- $curw))
    return 0
 }

Misc

Pay attention when using sudo that $HOME is still configured as yours and you could end up with some user config files owned by root in your own directory.
To avoid that, use "sudo -H" or to make it definitive, use visudo to add to the sudo conf: "Defaults always_set_home"

To convert ASCII Mac file to Unix file:

for file in *; do cat "$file" | tr \\15 \\12 >e;mv e "$file"; done

To convert a filename from uppercase to lowercase

for file in * ; do mv "$file" "$(echo -n $file|tr [[A-Z] [[a-z])" ; done

Boot Disk :

mkbootdisk numero version : voir version dans /lib/modules/2....
ou rdev -h : aide
rdev /boot/kernel - < nom du noyau
dd if=/boot/linux of=/dev/fd0 bs=8192

Conversion Ext2 -> Ext3

tune2fs -j /dev/hdXX

And don't forget to adapt fstab entry


Devinette

What is the output of this command?

echo one>/tmp/t;(echo two>/dev/stdout)>>/tmp/t;cat /tmp/t

Now, try...
Astonishing, isn't it?!
PS: to get what you expected, try >>/dev/stdout

Apparently when the command is executed, the sub-process is launched with /dev/stdout pointing to its /proc/self/fd/1 but this one is now set to /tmp/t so the sub-shell re-opens the file and overwrites it!

Note that under cygwin/bash, there is no real /dev/stdout and the result is one two

echo one>/tmp/t;m=$(echo two>/dev/stdout);echo $m>>/tmp/t;cat /tmp/t is working as expected, /proc/self/fd/1 of the sub-process is now a pipe to the main process.

So a program is able to detect if its output was redirected or not!

Little scripts

To constitute a dictionary for Scrabble from a french dict:

grep -v [-\'.] /usr/share/dict/french|unaccent ISO-8859-1|sort -u>scrabble-french

Usual prefixes:

cat scrabble-french |cut -c-3|uniq -c|sort -n -r|gawk '$1>1000{print $2}' 
cat scrabble-french |cut -c-2|uniq -c|sort -n -r|gawk '$1>2000{print $2}'

To find usual suffixes, invert the dictionary:

cat scrabble-french|tr "\n" "."|tac -r -s.|tr "." "\n"|sort>scrabble-suffix

Then find the most common suffixes:

 cat scrabble-suffix |cut -c-4|uniq -c|sort -n|gawk '$1>1000{print $2}'|tr "\n" "."|tac -r -s.|tr "." "\n"
 cat scrabble-suffix |cut -c-3|uniq -c|sort -n|gawk '$1>2000{print $2}'|tr "\n" "."|tac -r -s.|tr "." "\n"
 cat scrabble-suffix |cut -c-2|uniq -c|sort -n|gawk '$1>2000{print $2}'|tr "\n" "."|tac -r -s.|tr "." "\n"
 cat scrabble-suffix |cut -c-1|uniq -c|sort -n|gawk '$1>5000{print $2}'|tr "\n" "."|tac -r -s.|tr "." "\n"

History

To enable timestamps in the history, set the env variable (see 'man strftime')

HISTTIMEFORMAT='%F %T '

To convert timestamps from the history file

perl -e 'print scalar localtime(1141863326), "\n"'

To keep the history "forever", here is a nice .bashrc_history script to install
I adapted some stuff:

  • Enable timestamps on individual commands
  • Dates expressed as YY-MM-DD hh:mm:ss
  • Converted copy of the individual timestamps (requires gawk so enable it only if you have gawk, this is purely cosmetic as timestamps can be converted later if needed)
  • Trap HUP also as invoked bash from mc is apparently interrupted this way
 if [ "$PS1" ] ; then # interactive shell
-    export STARTTIME=`date` \
-           HISTORYDUMP=0
+    export STARTTIME=`date '+%Y-%m-%d %H:%M:%S'` \
+           HISTORYDUMP=0 \
+          HISTTIMEFORMAT='%F %T '
     shopt -s cmdhist histappend
 
     # Next function really stores the history logs. Besides that if you want to store whatever you have so far
     # you can call this function and it will save increment from the last call to it.
     archive_history()
     {
         TFILE=${HISTFILE}.$$.temp
-       CURTIME=`date`
+       CURTIME=`date '+%Y-%m-%d %H:%M:%S'`
        CURTTY=`tty`
         #STAMP
         HISTORYDUMP=$(($HISTORYDUMP+1))
         # Title
         echo "#$USER@${HOSTNAME} [ ${STARTTIME} - ${CURTIME} ]:$HISTORYDUMP ($CURTTY) ----" >| $TFILE
         # Fresh tasty history
        history -a ${TFILE}
         # Append it to the archive
-        cat ${TFILE} >> ${HISTFILE}.archive
+        #cat ${TFILE} >> ${HISTFILE}.archive
+       # But we add a converted version of the timestamp
+       gawk '/^#[0-9]+$/{print strftime("#%F %T ", gensub(/#/,"","g")) }//' ${TFILE} >> ${HISTFILE}.archive
         # Adjust history file itself
         # of cause we need to dump to some temp file and then rename... he heh
         cat ${HISTFILE} ${TFILE} | tail -${HISTSIZE} >| ${HISTFILE}.$$
         mv -f ${HISTFILE}.$$ ${HISTFILE}
         # clean up after yourself - to be absessive remove the other tmp file as well -
         # - might happen if there were no permission to move it at above point
         rm -rf ${TFILE} ${HISTFILE}.$$
     }
 
-    trap 'archive_history' EXIT
+    trap 'archive_history' EXIT HUP
     unset IGNOREEOF
 
 fi

And to install the script it is better to insert the following in ~/.bashrc

source ~/.bashrc_history

because e.g. with "vserver xxx enter" the shell is not started in the homedir
[UPDATE] now this "patch" is included in the upstream version, thanks Yaroslav!
Another nice tip from Yaroslav is to define another function in .bashrc_history:

gbha () { grep "$@" ~/.bash_history.archive; }

so you just type "gbha PATTERN" (gbha = grep bash history archive) to find what you need!

Examples

What did I install last?

gbha "^apt-get install"|tail

When did I modified syslog.conf?

gbha -B2 "syslog.conf"

What did I do that day between 10:00 and 11:59?

gbha -E -A2 "#2006-12-09 1[01]:"

Conversion d'une string hex en texte

Input: 48656c6c6f20776f726c640a
Output:Hello world


echo "48656c6c6f20776f726c640a" |\
    gawk  'BEGIN{FS=""};{for(i=1;i<=NF;i+=2)printf("%c",strtonum("0x"$i$(i+1)))}'

In Perl:


my $str = "02000501524550454154434f44453a323530";
print pack('C*', map { hex } unpack('(A2)*', $str));

Compter en hex

for ((i=0;i<65536;i++)) ; do f=$(printf "%0*X\n" 4 $i); echo $f;done

Fix sshd under Cygwin

Symptom: After IT policy...?? Can connect to sshd but visibly server cannot spawn to user shell
Fix

cygrunsrv -E sshd
cygrunsrv -R sshd
rm -rf /var/log/sshd* /etc/ssh_host* /etc/sshd_config /var/empty /tmp/ssh*
net user cyg_server /delete
net user sshd /delete
sed -i '/^cyg_server/d;/^sshd/d' /etc/passwd
ssh-host-config -y
ssh-user-config
cygrunsrv -S sshd

Note that "-d" debug option of ssh-host-config seems to interfere and installation fails if used.

Still troubleshooting new version...

  • delete privileged accounts (net user cyg_server /delete...)
  • fix? /usr/share/csih/cygwin-service-installation-helper.sh :
2990:     #if ! passwd -e "${csih_PRIVILEGED_USERNAME}" >/dev/null
2991-     if ! passwd -e "${csih_PRIVILEGED_USERWINNAME}" >/dev/null
  • see above, do it manually (ssh-host-config #-y) and change proposed DOMAINNAME+cyg_server privileged account in simpler "cyg" (otherwise apparently it's too long for passwd)
  • ? in /etc/fstab add "noacl":
none /cygdrive cygdrive binary,noacl,posix=0,user 0 0

Create quickly an empty file

Want to create e.g. a big file for a loop filesystem?
dd is way too slow
To allocate space (on filesystems supporting it, FAT doesn't)

fallocate -l 50G mystuff.img

Else, working on FAT:

truncate -s 50G mystuff.img

Then e.g.

/sbin/mkfs.ext3 mystuff.img
mkdir mystuff.mnt
sudo mount -o loop mystuff.img mystuff.mnt

DON'T TRY AT HOME

:(){ :|:& };: