Bash cheatsheet: Difference between revisions

From Lolly's Wiki
Jump to navigationJump to search
m (Text replacement - "<source " to "<syntaxhighlight ")
Line 6: Line 6:
=bash prompt=
=bash prompt=
Put this in your ~/.bash_profile
Put this in your ~/.bash_profile
<source lang=bash>
<syntaxhighlight lang=bash>
typeset +x PS1="\[\e]0;\u@\h: \w\a\]\u@\h:\w# "
typeset +x PS1="\[\e]0;\u@\h: \w\a\]\u@\h:\w# "
</source>
</source>
Line 13: Line 13:
==split==
==split==
For example split an ip:
For example split an ip:
<source lang=bash>
<syntaxhighlight lang=bash>
$ delimiter="."
$ delimiter="."
$ ip="10.1.2.3"
$ ip="10.1.2.3"
Line 22: Line 22:


==dirname==
==dirname==
<source lang=bash>
<syntaxhighlight lang=bash>
$ myself=/usr/bin/blafasel ; echo ${myself%/*}  
$ myself=/usr/bin/blafasel ; echo ${myself%/*}  
/usr/bin
/usr/bin
</source>
</source>
==basename==
==basename==
<source lang=bash>
<syntaxhighlight lang=bash>
$ myself=/usr/bin/blafasel ; echo ${myself##*/}  
$ myself=/usr/bin/blafasel ; echo ${myself##*/}  
blafasel
blafasel
</source>
</source>
==Path name resolving function==
==Path name resolving function==
<source lang=bash>
<syntaxhighlight lang=bash>
# dir_resolve originally from  http://stackoverflow.com/a/20901614/5887626
# dir_resolve originally from  http://stackoverflow.com/a/20901614/5887626
# modified at https://lars.timmann.de/wiki/index.php/Bash_cheatsheet
# modified at https://lars.timmann.de/wiki/index.php/Bash_cheatsheet
Line 50: Line 50:
==Reverse the order of elements==
==Reverse the order of elements==
An example for services in normal and reverse order for start/stop
An example for services in normal and reverse order for start/stop
<source lang=bash>
<syntaxhighlight lang=bash>
declare -a SERVICES_STOP=(service1 service2 service3 service4)
declare -a SERVICES_STOP=(service1 service2 service3 service4)
declare -a SERVICES_START
declare -a SERVICES_START
Line 59: Line 59:
</source>
</source>
This results in:
This results in:
<source lang=bash>
<syntaxhighlight lang=bash>
$ echo ${SERVICES_STOP[*]} ; echo ${SERVICES_START[*]}
$ echo ${SERVICES_STOP[*]} ; echo ${SERVICES_START[*]}
service1 service2 service3 service4
service1 service2 service3 service4
Line 79: Line 79:
Just put your code between <i>while</i> and <i>do</i> and use <i>continue</i> alias : in the loop.
Just put your code between <i>while</i> and <i>do</i> and use <i>continue</i> alias : in the loop.


<source lang=bash>
<syntaxhighlight lang=bash>
#!/bin/bash
#!/bin/bash
while
while
Line 90: Line 90:


For example:
For example:
<source lang=bash>
<syntaxhighlight lang=bash>
#!/bin/bash
#!/bin/bash


Line 104: Line 104:
=Functions=
=Functions=
==Log with timestamp==
==Log with timestamp==
<source lang=bash>
<syntaxhighlight lang=bash>
function printlog () {
function printlog () {
# Function:
# Function:
Line 134: Line 134:
</source>
</source>


<source lang=bash>
<syntaxhighlight lang=bash>
$ printf "test\n\ntoast\n" | printlog /dev/stdout
$ printf "test\n\ntoast\n" | printlog /dev/stdout
20190603 12:48:13 test
20190603 12:48:13 test
Line 147: Line 147:


=Calculations=
=Calculations=
<source lang=bash>
<syntaxhighlight lang=bash>
$ echo $[ 3 + 4 ]  
$ echo $[ 3 + 4 ]  
7  
7  
Line 156: Line 156:
=init scripts=
=init scripts=
==A basic skeleton==
==A basic skeleton==
<source lang=bash>
<syntaxhighlight lang=bash>
#!/bin/bash
#!/bin/bash


Line 211: Line 211:
= Logging and output in your scripts =
= Logging and output in your scripts =
== Add a timestamp to all output ==
== Add a timestamp to all output ==
<source lang=bash>
<syntaxhighlight lang=bash>
#!/bin/bash
#!/bin/bash


Line 240: Line 240:


== Add a timestamp to all output and send to file==
== Add a timestamp to all output and send to file==
<source lang=bash>
<syntaxhighlight lang=bash>
#!/bin/bash
#!/bin/bash


Line 273: Line 273:


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

Revision as of 00:39, 26 November 2021

Kategorie:Bash

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>