Bash cheatsheet

From Lolly's Wiki
Revision as of 23:54, 25 November 2021 by Lollypop (talk | contribs) (Text replacement - "[[Kategorie:" to "[[Category:")
Jump to navigationJump to search


bash history per user

See Logging the SSH fingerprint

bash prompt

Put this in your ~/.bash_profile <syntaxhighlight lang=bash> typeset +x PS1="\[\e]0;\u@\h: \w\a\]\u@\h:\w# " </source>

Useful variable substitutions

split

For example split an ip: <syntaxhighlight lang=bash> $ delimiter="." $ ip="10.1.2.3" $ declare -a octets=( ${ip//${delimiter}/ } ) $ echo "${#octets[@]} octets -> ${octets[@]}" 4 octets -> 10 1 2 3 </source>

dirname

<syntaxhighlight lang=bash> $ myself=/usr/bin/blafasel ; echo ${myself%/*} /usr/bin </source>

basename

<syntaxhighlight lang=bash> $ myself=/usr/bin/blafasel ; echo ${myself##*/} blafasel </source>

Path name resolving function

<syntaxhighlight lang=bash>

  1. dir_resolve originally from http://stackoverflow.com/a/20901614/5887626
  2. modified at https://lars.timmann.de/wiki/index.php/Bash_cheatsheet

dir_resolve() {

 local dir=${1%/*}
 local file=${1##*/}
 # if the name does not contain a / leave file blank or the name will be name/name
 [ "_${1/\//}_" == "_${1}_" -a -d ${1} ] && file=""
 [ "_${1/\//}_" == "_${1}_" -a -f ${1} ] && dir=""
 pushd "$dir" &>/dev/null || return $? # On error, return error code
 echo ${PWD}${file:+"/"${file}} # output full path with filename
 popd &> /dev/null

} </source>

Arrays

Reverse the order of elements

An example for services in normal and reverse order for start/stop <syntaxhighlight lang=bash> declare -a SERVICES_STOP=(service1 service2 service3 service4) declare -a SERVICES_START for(( i=$[ ${#SERVICES_STOP[*]} - 1 ] ; i>=0 ; i-- )) do

 SERVICES_START+=(${SERVICES_STOP[$i]})

done </source> This results in: <syntaxhighlight lang=bash> $ echo ${SERVICES_STOP[*]} ; echo ${SERVICES_START[*]} service1 service2 service3 service4 service4 service3 service2 service1 </source>


Loops

Numbers

$ for i in {0..9} ; do echo $i ; done

or

$ for ((i=0;i<=9;i++)); do echo $i; done

so gehen natürlich auch andere Sprünge, z.B. immer 3 weiter:

$ for ((i=0;i<=9;i+=3)); do echo $i; done

or or or

$ for ((i=0,j=1;i<=9;i+=3,j++)); do echo "$i $j"; done

Exit controlled loop

Just put your code between while and do and use continue alias : in the loop.

<syntaxhighlight lang=bash>

  1. !/bin/bash

while

 # some code
 (( <your control expression> ))

do

 :

done </source>

For example: <syntaxhighlight lang=bash>

  1. !/bin/bash

i=1 while

 i=$[ $i + 1 ];
 (( $i < 10 ))

do

 :

done </source>

Functions

Log with timestamp

<syntaxhighlight lang=bash> function printlog () {

  1. Function:
  2. Log things to logfile
  3. Parameter:
  4. 1: logfile
  5. *: You can call printlog like printf (except the first parameter is the logfile)
  6. OR
  7. Just pipe things to printlog
 local logfile=${1}
 shift
 if [ -n "${*}" ]
 then
   format=${1}
   shift
   printf "%s ${format}" "$(/bin/date '+%Y%m%d %H:%M:%S')" ${*} >> ${logfile}
 else
   while read input
   do
     printf "%s %s\n" "$(/bin/date '+%Y%m%d %H:%M:%S')" "${input}" >> ${logfile}
   done
 fi

} </source>

<syntaxhighlight lang=bash> $ printf "test\n\ntoast\n" | printlog /dev/stdout 20190603 12:48:13 test 20190603 12:48:13 20190603 12:48:13 toast $ printlog /dev/stdout "test\n" 20190603 12:48:19 test $ printlog /dev/stdout "test %s %d %s\n" "bla" 0 "bli" 20190603 12:48:25 test bla 0 bli $ </source>

Calculations

<syntaxhighlight lang=bash> $ echo $[ 3 + 4 ] 7 $ echo $[ 2 ** 8 ] # 2^8 256 </source>

init scripts

A basic skeleton

<syntaxhighlight lang=bash>

  1. !/bin/bash

NAME=<myname> # The name of the daemon USER=<runuser> # The user to run the daemon as

SELF=${0##*/} CALLER=$(id -nu)

  1. Check if called as ${USER}

if [ "_${CALLER}_" != "_${USER}_" ] then

 # If not do a su if called as root
 if [ "_${CALLER}_" == "_root_" ]
 then
   exec su -l ${USER} -c "$0 $@"
 else
   echo "Please start this script only as user ${USER}"
   exit 1
 fi

fi


if [ $# -eq 1 ] then

 command=$1

else

 # Called as ${NAME}-start.sh or ${NAME}-stop.sh
 command=${SELF%.sh}
 command=${command##${NAME}-}
 [ "_${command}_" == "_${NAME}_" ] && command=""

fi

case ${command} in start)

 # start commands
 ;;

stop)

 # stop commands
 ;;

restart)

 $0 stop
 $0 start
 ;;
  • )
 [ ! -z "${command}" ] && echo "ERROR: Unknown option ${command}!"
 echo "Usage: $0 (start|stop|restart)";
 echo "Or call as ${NAME}-(start|stop|restart).sh"
 exit 1
 ;;

esac </source>

Logging and output in your scripts

Add a timestamp to all output

<syntaxhighlight lang=bash>

  1. !/bin/bash
  1. Find temp filename

FIFO=$(mktemp)

  1. Clenup on exit

trap 'rm -f ${FIFO}' 0

  1. Delete file created by mktemp

rm "${FIFO}"

  1. Create a FIFO instead

mkfifo "${FIFO}"

  1. Read from FIFO and add date at the beginning

sed -e "s|^|$(date '+%d.%m.%Y %H:%M:%S') :: |g" < ${FIFO} &

  1. Redirect stdout & stderr to FIFO

exec > ${FIFO} 2>&1

  1. Now your program

echo bla echo bli >&2 </source>

Add a timestamp to all output and send to file

<syntaxhighlight lang=bash>

  1. !/bin/bash

LOGFILE=/tmp/bla.log

  1. Find temp filename

FIFO=$(mktemp)

  1. Clenup on exit

trap 'rm -f ${FIFO}' 0

  1. Delete file created by mktemp

rm "${FIFO}"

  1. Create a FIFO instead

mkfifo "${FIFO}"

  1. Read from FIFO and add date at the beginning

sed -e "s|^|$(date '+%d.%m.%Y %H:%M:%S') :: |g" < ${FIFO} > ${LOGFILE}&

  1. Redirect stdout & stderr to FIFO

exec > ${FIFO} 2>&1

  1. Now your program

echo bla echo bli >&2 </source>

Parameter parsing

In progress... no time... <syntaxhighlight lang=bash> while [ $# -gt 0 ] do

 case $1 in
 -h|--help)
   usage help
   shift;
   exit 0;
   ;;
 --?*=?*|-?*=?*)
   param=${1%=*}
   value=${1#*=}
   shift;
   ;;
 --?*=|-?*=)
   param=${1%=*}
   usage "${param} needs a vlaue!"
   ;;
 *)
   if [ $# -lt 2 ] ; then usage "$1 needs a value!"; fi
   param=$1
   value=$2
   shift; shift;
   ;;
 esac
 case $param in
 *)
   other_params[$[${#other_params[*]} + 1]]="${param}=${value}"
   param=${param#--}
   param=${param/-/_}
   export ${param^^}=${value}
   ;;
 esac

done </source>