Bash
From Blue-IT.org Wiki
Contents
Environment
Put this in front of any script to avoid problems when running the script in other languages! The en_US locale should be avaiabel on all systems:
export LC_MESSAGES="en_US.UTF-8" export LC_TYPE="en_US.UTF-8" export LANGUAGE="en_US.UTF-8
Terminal or GUI
You can determine, if a script is running in a terminal (TTY) or within a gui:
# check, if we are running in a terminal if tset -q | grep linux then echo "Running in terminal session ... continue the script " GUI=0 else # Open a GUI dialog if zenity --question --title "GUI Dialog" \ --text "Would you like to continue?" then # set some vars GUI=1 else exit 1 fi fi
Sending mails
mailx - former known as nail
Tested in
- Ubuntu 12.04
- Ubuntu 14.04
Tested with:
- gmx
Inspired by
Install packages
sudo apt-get install ca-certificates heirloom-mailx msmtp
Edit configuration files
One for msmtp:
vim ~/.msmtprc
# config options: http://msmtp.sourceforge.net/doc/msmtp.html#A-user-configuration-file defaults logfile /tmp/msmtp.log # settings for gmx account gmx auth on host mail.gmx.de port 587 user username@gmx.de from username@gmx.de password PASSHERE tls on tls_trust_file /etc/ssl/certs/ca-certificates.crt # settings for google account gmx auth on host smtp.gmail.com port 587 user username@gmail.com from username@gmail.com password PASSHERE tls on tls_trust_file /etc/ssl/certs/ca-certificates.crt # set default account to account default: gmx
One for mailx:
vim ~/.mailrc
# set smtp for mailx # (default) set from="username@gmx.de" set sendmail="/usr/bin/msmtp" set message-sendmail-extra-arguments="-a gmx" account gmx { set from="username@gmx.de (Your name) send from command line" set sendmail="/usr/bin/msmtp" set message-sendmail-extra-arguments="-a gmx" } account google { set from="username@gmail.com (Your Name) send from command line" set sendmail="/usr/bin/msmtp" set message-sendmail-extra-arguments="-a google" }
Send the mail
mailx -A gmx -s "gmx test" username@gmx.de < /tmp/test_email.txt echo "mail text" | mailx -A gmx -s "gmx test" username@gmx.de cat /tmp/test_email.txt | mailx -A gmx -s "gmx test" username@gmx.de
Sending an attachment
echo "mail text" | mailx -A gmx -a attachment.file -s "gmx test" username@gmx.de
Sending dmesg message (or other) via pipe
dmesg | mailx -A gmx -s "$HOSTNAME dmesg" username@gmx.de
Explanation:
-A xxx : the name of the isp account that must match in ~/.msmtprc AND .mailrc. If not specified, the as default defined account will be used. -s "Text" : the subject -a Datei : Attachment
Singleton
The singleton pattern is a very handy one. You can realise it in bash like this:
if ps x | grep -v grep | grep -v $$ | grep $0 | grep -v subl | grep -v vi then echo "$0 already running. Exiting" exit 1 else ################################################ # PUT YOUR CODE HERE # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ./run_me # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ################################################ fi
Grep
Grep a steam with tail, head
Sometimes you need not to filter a standard out only once, but with tail
tail -f -n 300 /var/log/syslog | stdbuf -o0 grep PATTERN
remove empty lines
cat some_text | egrep -v '^#|^$'
remove carriage return (newline
echo "something" | tr -d '\n'
Graphical Tools
Sometimes you need to get out of yor script, give a message to your users - visually.
notify-send
#!/bin/bash notify_start() { aplay Critical_Error.wav notify-send "Backup is is mounted." \ -i /usr/share/icons/gnome/48x48/actions/document-open-recent.png \ "Read and write support for you is working." } notify_end() { notify-send "Backup Drive is not ready!" \ -i /usr/share/icons/gnome/48x48/actions/stock-delete.png \ "Resolve the problem and save your work" } while(true); do if touch /backup/testfile then rm /backup/testfile notify_start else notify_end fi sleep 10 done
Monitoring
Sometimes you like to run a monitor in the background. Here an example for checking if a drive had an drive error.
#!/bin/bash if ps x | grep -v grep | grep -v $$ | grep $0 | grep -v subl | grep -v vi then echo "$0 already running. Exiting" exit 1 else ################################################ # PUT YOUR CODE HERE # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv notify_start() { aplay /local/share/sounds/KDE_Critical_Error.wav notify-send "Backup is is mounted." \ -i /usr/share/icons/gnome/48x48/actions/document-open-recent.png \ "Read and write support for you is working." } notify_end() { aplay /local/share/sounds/KDE_Critical_Error.wav notify-send "Backup Drive is not ready!" \ -i /usr/share/icons/gnome/48x48/actions/stock-delete.png \ "Resolve the problem and save your work" } while(true); do message_head="SSD WRITE TEST:" message_time="date +%F_%Hh:%Ms:%Nms" error="ERROR:" logger "${message_head} $(${message_time}) starting sync" if sync then logger "${message_head} $(${message_time}) sync finished successfully." else logger "${message_head} $(${message_time}) ${error} while do sync." fi sleep 2 if touch ~/testfile then logger "${message_head} $(${message_time}) touched testfile in home successfully." if rm ~/testfile then logger "${message_head} $(${message_time}) removed testfile in home successfully." else logger "${message_head} $(${message_time}) ${error} while removing tesfile in home." fi else logger "${message_head} $(${message_time}) ${error} while touching tesfile in home." notify_end fi sleep 28 done # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ################################################ fi
sed
Search and replace text in a document with sed
# Search and replace text in a document globally or first # apos@gmx.de - 2008 # # param1: search string # param2: replace string # param3: the document URL search_replace_global(){ search="$(printf "%s\n" "${1}" | sed 's/[][\.*^$/]/\\&/g')" replace="$(printf "%s\n" "${2}" | sed 's/[][\.*^$/]/\\&/g')" sed -i "s/${search}/${replace}/g" "${3}" } search_replace_first(){ search="$(printf "%s\n" "${1}" | sed 's/[][\.*^$/]/\\&/g')" replace="$(printf "%s\n" "${2}" | sed 's/[][\.*^$/]/\\&/g')" sed -i "s/${search}/${replace}/" "${3}" }
Cut text out of a file
# Cut text out of a file. # Searches for the first (!) - and only the first - occurence of the Expression # "FIRST_TEXT_FRAGMENT" and then, from that line on to the first occurence of # "LAST_TEXT_FRAGMENT". It then cuts the lines between these two - # including the found lines (!) - out with sed. # # param1: first text fragment # param2: second text fragment # param3: input file - the file to inspect cut_text(){ THEDOC="${3}" #FIRST_TEXT_FRAGMENT="$(printf "%s\n" "${1}" | sed 's/[][\.*^$/]/\\&/g')" FIRST_TEXT_FRAGMENT="${1}" #LAST_TEXT_FRAGMENT="$(printf "%s\n" "${2}" | sed 's/[][\.*^$/]/\\&/g')" LAST_TEXT_FRAGMENT="${2}" BEGIN_CUT=$(cat ${THEDOC} | fgrep -n --max-count=1 "${FIRST_TEXT_FRAGMENT}" | cut -d':' -f1) BEGIN_CUT=$(expr ${BEGIN_CUT}) echo ${BEGIN_CUT} END_CUT=$(cat ${THEDOC} | sed -e "1,${BEGIN_CUT}d" | fgrep -n --max-count=1 "${LAST_TEXT_FRAGMENT}" | cut -d':' -f1) echo ${END_CUT} END_CUT=$(expr ${END_CUT} + ${BEGIN_CUT}) echo ${END_CUT} sed -i "${BEGIN_CUT},${END_CUT}d" "${THEDOC}" }
rename
find . -depth -name "*.*" -execdir rename 's/:/_/g;s/:/_/g;s/</_/g;s/>/_/g;s/$/_/g;' "{}" \;