return value:
any exit/return/result value other than
0
is considered an error.
you can output the return value of the last command like this:
echo $? 0
inside a script you can exit and return an exit code like this:
exit 123; # will exit program with exit code 123
about [ test ]
[ is a binary program. no joke 😀
the ] closing bracket is signaling [ that the list of arguments is complete
It is said to be equivalent to the test command.
Instead of
if /usr/bin/test -z "$VAR" then echo VAR not set fi # You can use: if /usr/bin/[ -z "$VAR" ] then echo VAR not set fi
src: https://superuser.com/questions/334549/what-is-usr-bin-and-how-do-i-use-it
which [ /usr/bin/[ user@Debian8:~$ man [ # but it's not a softlink to test and also not exaclty the same binary as /usr/bin/test file /usr/bin/[ /usr/bin/[: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=c2f4f0658df93da072fa87527ce92c92c1bc1bdd, stripped file /usr/bin/test /usr/bin/test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=477413f30b2afe76b51b5ca9d81bd2f2a641c095, stripped # possible things you can test for # test if file exists (directories under linux are also just special files - hence it returns also true for directories) if [ -e /path/file ]; then echo "exists"; else echo "does not exist"; fi # file exists and is readable if [ -r /path/file ]; then echo "exists"; else echo "does not exist"; fi # file exists and is writable if [ -w /path/file ]; then echo "exists"; else echo "does not exist"; fi # file exists and is runnable if [ -x /path/file ]; then echo "exists"; else echo "does not exist"; fi
# file exists and is a directory if [ -d /path/file ]; then echo "exists"; else echo "does not exist"; fi
# file exists and is a block device if [ -b /path/file ]; then echo "true"; else echo "false"; fi
# file exists and is a char device if [ -c /path/file ]; then echo "true"; else echo "false"; fi
# file exists and has GUID bit set if [ -g /path/file ]; then echo "true"; else echo "false"; fi # file exists and has the sticky bit set if [ -k /path/file ]; then echo "true"; else echo "false"; fi # file exists and has the SUID bit set if [ -u /path/file ]; then echo "true"; else echo "false"; fi
# file exists and is a regular file if [ -f /path/file ]; then echo "true"; else echo "false"; fi # file exists and is a symbolic link if [ -L /path/file ]; then echo "true"; else echo "false"; fi # tests if file1 newer than file2 if [ file1 -nt file2 ]; then echo "true"; else echo "false"; fi # tests if file1 older than file2 if [ file1 -ot file2 ]; then echo "true"; else echo "false"; fi # tests if variable A equals B if [ $A -eq $B ]; then echo "true"; else echo "false"; fi # tests if variable A is uniqual to B if [ $A -ne $B ]; then echo "true"; else echo "false"; fi # tests if variable A is greater than B (integer expected, will not work with strings or float) if [ $A -gt $B ]; then echo "true"; else echo "false"; fi # tests if variable A is greater or equal to B (integer expected, will not work with strings or float) if [ $A -ge $B ]; then echo "true"; else echo "false"; fi # tests if variable A is less than B (integer expected, will not work with strings or float) if [ $A -lt $B ]; then echo "true"; else echo "false"; fi # tests if variable A is less or equal than B (integer expected, will not work with strings or float) if [ $A -le $B ]; then echo "true"; else echo "false"; fi
customize $PATH autocomplete
# $PATH is a system variable (environment variable bash settings variable) in which bash searches for executable binaries and scripts. # change to your home directory cd # create new directory mkdir bin # add this directory to $PATH export PATH=$PATH:$HOME/bin; # add custom path to path and make it available to sub-bashs (export (otherwise just valid in current bash) vim bin/script1.sh; # create a new script, with those lines #!/bin/bash echo "Enter your name...." read sname echo "hello $sname"; ESC :x # save and quit in vim # you could run the script now with bash bin/script1.sh # but every script needs the executable right set to function properly chmod +x bin/script1.sh; # set's execute rights for everybody (owner,group,others) # now if you type scr... TAB user@Debian8:~$ scr screendump script script1.sh scriptreplay # bash nicely autocompletes your custom script
if then else
vim bin/script2.sh; # lets make a new script, with those lines
#!/bin/bash
if [[ $1 = "d" ]]
then
find /etc -maxdepth 1 -type d; # search only for directories under /etc
else
find /etc -maxdepth 1 -type l; # search only for symbolic links under /etc
fi
ESC :x # save and quit in vim
chmod +x !$; # mark script runnable
# or
chmod +x bin/script2.sh
# !$ is represents the last argument (only the last one - not multiple) used in the last command
loops
# as you might know loops repeat a command a certain amount of times - depending on number of times or other if-conditions # become root su # or sudo bash
for loop
# this line will add 10 new users with random passwords for u in $(seq 10) ; do useradd user$u; echo user${u}:Password1 | chpasswd -c SHA512; done # will remove the 10 just added users again for u in $(seq 10) ; do userdel -r user$u; done
loop iterate over a list of found files
vi show_all.sh; # create a new file with those lines
#!/bin/bash
# this script will search case-insensitive your whole filesystem for SEARCH_PATTERN
# it will pause when SEARCH_PATTERN was found and output:
#
# file: show path of file
# content: content of file 100 chars before and 100 chars after SEARCH_PATTERN, non-printable chars will be displayed as well by cat -v
SEARCH_PATTERN=$1
echo "...case-insensitive searching for: \"$SEARCH_PATTERN\"";
echo "...please stand by.";
# for z in $(find /) # would be equally correct
for z in `find /`
do
# test if SEARCH_PATTERN exists in /path/file
echo "$z";
if grep -q -i $SEARCH_PATTERN "$z" 2> /dev/null; then
clear; # grep found something make space on monitor
echo -e "\n===================================================================="; # visual separator
echo "file: $z";
echo -e "\ncontent: ";
# cat -v "$z" | grep --color=auto -iaPo ".{0,100}$SEARCH_PATTERN.{0,100}"; # will display 100 chars before and after string was found
cat -v "$z" | grep --color=auto -i $SEARCH_PATTERN; # will only display content of text-files
echo -e "\n";
read; # wait for user to hit enter
fi
done
unset z
exit 0
./show_all.sh torvalds & # search for the kernel-master
while loop
# while being in your home directory
vi bin/script3.sh; # create a new file with those lines
#!/bin/bash
COUNT=10
while (( COUNT > 0 ))
do
echo -e "$COUNT \c"
sleep 1;
(( COUNT -- ))
done
echo -e "\n\nWe have lift off!!"
ESC :x # save and quit vi
# mark the script as runnable
chmod +x !$; # mark script runnable
# or
chmod +x bin/script3.sh
# and run it - nice countdown
arguments
arguments are the input of a script
vim count_arguments.sh; # create a new file with those lines #!/bin/bash echo "the script was started with $0" echo "you have passed it $# parameters" ./count_arguments.sh the script was started with ./count_arguments.sh you have passed it 0 parameters ./count_arguments.sh 1 the script was started with ./count_arguments.sh you have passed it 1 parameters ./count_arguments.sh 1 2 the script was started with ./count_arguments.sh you have passed it 2 parameters ./count_arguments.sh 1 2 3 the script was started with ./count_arguments.sh you have passed it 3 parameters vim ./add_multiple_arguments.sh; # create a new file with those lines #!/bin/bash # pass multiple numbers as arguments that this script will add up sum=0; # initialize this variable with an value, so one can be sure it is set to that value while test $# -gt 0 do let sum=sum+$1 shift done echo the sum of all your input is $sum unset sum; exit 0; ./add.sh 1 2 3 4 5 6; # testrun the sum of all your input is 21
script exit codes error signal handling
scripts not only can output data to screen or files… they also return error-codes to report if everything went as planned or not…
under unix/linux – an error code of zero means “ok” while anything else might signal an error.
vim mail_test.sh; # create a new file with those lines #!/bin/bash DF=$HOME/df.txt if [ -e $DF ]; # test if file exists then echo "The file exists!!" exit 2; # exit with (error)status of 2 (anything but zero is considered an error result) fi df -hT > $DF; # write output of command df to /path/file in $DF variable mail -s "Disk free $(date +%F)" root < $DF; # mail to root rm -f $DF; # remove file ESC :x # save and quit chmod +x !$; # mark script runnable # strange enough this does not send a local mail to root but to normal user UID 1000 # this is because of an defined alias in /etc/aliases # all mails to root will be forwarded to first standard-user "user" (UID 1000) cat /etc/aliases |grep root: root: user # so if you open up mail # you should have mail (try root and non root user) mail Mail version 8.1.2 01/15/2001. Type ? for help. "/var/mail/user": 1 message 1 new >N 1 user@debian Tue Jun 13 12:12 24/979 Disk free 2017-06-13 & 1 Message 1: From user@debian Tue Jun 13 12:12:10 2017 Envelope-to: root@debian Delivery-date: Tue, 13 Jun 2017 12:12:10 +0200 To: root@debian Subject: Disk free 2017-06-13 From: user <user@debian> Date: Tue, 13 Jun 2017 12:12:10 +0200 Filesystem Type Size Used Avail Use% Mounted on /dev/sda1 ext4 123G 2.7G 115G 3% / udev devtmpfs 10M 0 10M 0% /dev tmpfs tmpfs 202M 5.0M 197M 3% /run tmpfs tmpfs 503M 76K 503M 1% /dev/shm tmpfs tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs tmpfs 503M 0 503M 0% /sys/fs/cgroup /dev/sdc1 ext3 9.8G 3.0G 6.3G 33% /home tmpfs tmpfs 101M 12K 101M 1% /run/user/1000 # but the interesting part is the exit code handling user@Debian8:~$ echo $?; # checkout the error code of the last run script or command 0 # no output = script worked fine = result / exit code = 0 (zero) this_command_does_not_exist echo $?; # results into error code 127 -bash: 127: command not found # any exitcode that is non-zero is regarded as error touch $HOME/df.txt; # create that file ./mail_test.sh; # then run script again The file exists!! # the scrpit now exits with / returns the script-defined error code 2 echo $? 2
Basic Arithmetics
links:
https://bash.cyberciti.biz/guide/Perform_arithmetic_operations
http://www.theunixschool.com/2012/03/typeset-arithmetic-operations.html
vim add.sh; # create a new script, with those lines #!/bin/bash # adds two numbers let summe=$1+$2 echo "the sum of $1 and $2 is $summe" ESC :x # save and quit in vim chmod +x add.sh; # mark it runnable ./add.sh 5 12; # test it the sum of 5 and 12 is 17 typeset -i number number=301*2; # multiplication echo $number 602 number=$number+1; # addition number=$number/3; # division echo $number 201 number=8\<\<3; # bit shifting 64 # because number was defined as integer (typeset -i) it is not allowed to store strings or float in it # this is important for clean programming number=8.3 -bash: 8.3: syntax error: invalid arithmetic operator (error token is ".3")
liked this article?
- only together we can create a truly free world
- plz support dwaves to keep it up & running!
- (yes the info on the internet is (mostly) free but beer is still not free (still have to work on that))
- really really hate advertisement
- contribute: whenever a solution was found, blog about it for others to find!
- talk about, recommend & link to this blog and articles
- thanks to all who contribute!