This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
program_lang:bash [2021/01/01 21:25] 127.0.0.1 external edit |
program_lang:bash [2024/04/17 16:06] (current) manu |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== BASH ====== | ====== BASH ====== | ||
+ | |||
+ | ===== IF ===== | ||
+ | |||
+ | if or compare text | ||
+ | if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ] | ||
+ | if [ $a == $b -o $b == $c -o $a == $c ] | ||
+ | | ||
+ | if and | ||
+ | if [ $a == $b -a $b == $c -a $a == $c ] | ||
+ | if [ "$fname" = "a.txt" ] && [ "$fname" = "c.txt" ] | ||
+ | |||
+ | ===== Use CSV file ===== | ||
+ | |||
+ | ==== Change column order ==== | ||
+ | |||
+ | Switch column 1 and 3 serared by ; | ||
+ | <cli prompt='#'> | ||
+ | [root@lnx01 ~]# echo "1;2;3;4;5" | awk -F';' '{ t = $3 ; $3 = $1; $1 = t; print; }' OFS=';' | ||
+ | 3;2;1;4;5 | ||
+ | </cli> | ||
+ | |||
+ | ===== backup files and folders permissions ===== | ||
+ | |||
+ | Here an easy way to convert **rwx** in octal | ||
+ | <cli prompt='#'> | ||
+ | [root@lnx01 ~]# find ./ -printf '%m:%u:%g:%p\0\n' | ||
+ | 750:root:root:./libiconv-1.14-3.aix5.1.ppc.rpm | ||
+ | 750:root:root:./libraqm-0.7.0-4.el7.src.rpm | ||
+ | 755:root:root:./libssl.so.1.0.2 | ||
+ | 700:root:root:./rpmbuild | ||
+ | 700:root:root:./rpmbuild/SOURCES | ||
+ | 664:root:root:./rpmbuild/SOURCES/raqm-0.7.0.tar.gz | ||
+ | 700:root:root:./rpmbuild/SPECS | ||
+ | 644:root:root:./rpmbuild/SPECS/libraqm.spec | ||
+ | 750:root:root:./libraqm-0.7.0-4.el7.x86_64.rpm | ||
+ | 750:root:root:./libwebp7-1.0.3-1.el7.remi.x86_64.rpm | ||
+ | 750:root:root:./php-mbstring-7.4.24-1.fc33.remi.x86_64.rpm | ||
+ | 700:root:root:./php56-php-mbstring-5.6.40-28.el7.remi.x86_64.rpm | ||
+ | </cli> | ||
+ | |||
+ | Here another more advanced output, with UID, GID... | ||
+ | <cli prompt='#'> | ||
+ | [root@lnx01 ~]# find ./ -printf '%Y:%m:%U:%G:%a:%p\0\n' | ||
+ | f:750:0:0:Fri Oct 15 02:29:02.0764754025 2021:./libraqm-0.7.0-4.el7.src.rpm | ||
+ | f:755:0:0:Fri Oct 15 02:29:02.0789754200 2021:./libssl.so.1.0.2 | ||
+ | d:700:0:0:Sun Oct 17 10:34:56.0564143056 2021:./rpmbuild | ||
+ | d:700:0:0:Sun Oct 17 23:08:59.0437891139 2021:./rpmbuild/SOURCES | ||
+ | f:664:0:0:Fri Oct 15 02:29:02.0837754536 2021:./rpmbuild/SOURCES/raqm-0.7.0.tar.gz | ||
+ | d:700:0:0:Sun Oct 17 23:08:59.0437891139 2021:./rpmbuild/SPECS | ||
+ | f:644:0:0:Fri Oct 15 02:29:02.0863754718 2021:./rpmbuild/SPECS/libraqm.spec | ||
+ | f:750:0:0:Fri Oct 15 02:29:02.0863754718 2021:./libraqm-0.7.0-4.el7.x86_64.rpm | ||
+ | f:750:0:0:Fri Oct 15 02:29:02.0863754718 2021:./libwebp7-1.0.3-1.el7.remi.x86_64.rpm | ||
+ | f:750:0:0:Fri Oct 15 02:29:02.0873754788 2021:./php-mbstring-7.4.24-1.fc33.remi.x86_64.rpm | ||
+ | f:700:0:0:Fri Oct 15 02:29:02.0893754927 2021:./php56-php-mbstring-5.6.40-28.el7.remi.x86_64.rpm | ||
+ | </cli> | ||
+ | |||
+ | |||
+ | ===== compare decimal ===== | ||
+ | |||
+ | Error message when comparing 2 number, when decimal are user | ||
+ | integer expression expected | ||
+ | |||
+ | You can use **bc** | ||
+ | Ex: | ||
+ | <cli> | ||
+ | size=10.5 | ||
+ | max_sz=10 | ||
+ | |||
+ | if [[ $(bc <<<"${size} > ${max_sz}") == "1" ]] | ||
+ | then | ||
+ | echo "${size} is bigger than ${max_sz}" | ||
+ | fi | ||
+ | </cli> | ||
+ | |||
+ | ===== basename ===== | ||
+ | |||
+ | Error when using basename command | ||
+ | <cli prompt='$'> | ||
+ | [storage@lnx01l scripts]$ basename $0 | ||
+ | basename: invalid option -- 'b' | ||
+ | Try 'basename --help' for more information. | ||
+ | </cli> | ||
+ | |||
+ | <cli prompt='$'> | ||
+ | [storage@lnx01l scripts]$ basename -- $0 | ||
+ | -bash | ||
+ | </cli> | ||
+ | |||
+ | You can also use the first occurence when using **su** | ||
+ | instead su - myuser -c "myprog.sh" | ||
+ | use su - myuser "myprog.sh" | ||
+ | |||
+ | **Explanation:** When you execute the script in the context of the running shell (which is started via the "-c" option of su), that makes it an interactive shell (hence the -bash is the value of $0). So the "basename -bash" fails as "-b" is not a valid option... | ||
+ | |||
===== array ===== | ===== array ===== | ||
Line 25: | Line 119: | ||
arr=( $(ls) ) Save ls output as an array of files | arr=( $(ls) ) Save ls output as an array of files | ||
${arr[@]:s:n} Retrieve n elements starting at index s | ${arr[@]:s:n} Retrieve n elements starting at index s | ||
+ | |||
+ | Exemple | ||
+ | <cli prompt='#'> | ||
+ | #!/usr/bin/bash | ||
+ | declare -a Users=('user01' '1001' '1000' '' '' '/bin/bash') | ||
+ | Users+=('user02' '1002' '1003' '' '' '/bin/bash') | ||
+ | Users+=('user03' '1003' '4' 'Recovery user' '' '/bin/bash') | ||
+ | |||
+ | UserNbProps=6 | ||
+ | let NbUsers=${#Users[@]}/$UserNbProps | ||
+ | |||
+ | for (( i=0; i<$NbUsers; i++ )) | ||
+ | do | ||
+ | let ArrayIndex=i*UserNbProps | ||
+ | Line=$(cat /etc/passwd | grep "^${Users[$ArrayIndex]}:") | ||
+ | if [ -z "$Line" ] | ||
+ | then | ||
+ | echo "# ${Users[$ArrayIndex]} user was not found" | ||
+ | else | ||
+ | Uid=$(echo $Line | cut -d: -f3) | ||
+ | Gid=$(echo $Line | cut -d: -f4) | ||
+ | UidRef=${Users[$ArrayIndex+1]} | ||
+ | GidRef=${Users[$ArrayIndex+2]} | ||
+ | if [ $Uid != $UidRef -o $Gid != $GidRef ] | ||
+ | then | ||
+ | echo "# User: ${Users[$ArrayIndex]} uid:$Uid gid:$Gid does not match reference uid:$UidRef gid:$GidRef" | ||
+ | fi | ||
+ | fi | ||
+ | done | ||
+ | </cli> | ||
| | ||
+ | ===== Read files ===== | ||
+ | |||
+ | read only first line | ||
+ | head -1 myfile.txt | ||
| | ||
+ | read 5 last lines | ||
+ | tail -5 myfile.txt | ||
+ | |||
+ | read the file without header (first line) | ||
+ | awk 'NR>1' myfile.txt | ||
| | ||
+ | ===== trap ===== | ||
+ | |||
+ | The format of the trap command is: | ||
+ | <cli prompt='#'> | ||
+ | # trap 'command_list' signals | ||
+ | </cli> | ||
+ | |||
+ | To ignore a signal, use two single quotes in place of the command_list: | ||
+ | <cli prompt='#'> | ||
+ | # trap '' signals | ||
+ | </cli> | ||
+ | |||
+ | To reset a trap use: | ||
+ | <cli prompt='#'> | ||
+ | # trap ‑ signals | ||
+ | </cli> | ||
+ | |||
+ | **Example** | ||
+ | <cli> | ||
+ | #!/bin/bash | ||
+ | #trapoff_on | ||
+ | |||
+ | trap '' SIGINT SIGQUIT | ||
+ | echo "you cannot terminate using ctrl‑c or ctrl‑\, " | ||
+ | #heavy pressing go on here, cannot interrupt ! | ||
+ | sleep 10 | ||
+ | |||
+ | trap 'echo terminated; exit' SIGINT SIGQUIT | ||
+ | #user can now interrupt | ||
+ | echo "ok you can now terminate me using those keystrokes" | ||
+ | sleep 10 | ||
+ | </cli> | ||
+ | |||
+ | Example, to remove a file | ||
+ | <cli> | ||
+ | trap 'rm /tmp/hold∗.$$; exit' SIGNHUP SIGINT SIGQUIT SIGTERM | ||
+ | </cli> | ||
+ | |||
+ | === For info === | ||
+ | |||
+ | To view the signals and their default actions (on an AIX machine), view the file: | ||
+ | <cli prompt='$'> | ||
+ | $ cat /usr/include/sys/signal.h | more | ||
+ | ….. | ||
+ | ….. | ||
+ | #define SIGHUP 1 /∗ hangup, generated when terminal disconnects ∗/ | ||
+ | #define SIGINT 2 /∗ interrupt, generated from terminal special char ∗/ | ||
+ | #define SIGQUIT 3 /∗ (∗) quit, generated from terminal special char ∗/ | ||
+ | #define SIGILL 4 /∗ (∗) illegal instruction (not reset when caught)∗/ | ||
+ | #define SIGTRAP 5 /∗ (∗) trace trap (not reset when caught) ∗/ | ||
+ | #define SIGABRT 6 /∗ (∗) abort process ∗/ | ||
+ | ... | ||
+ | </cli> | ||
+ | |||
+ | You can use either signal name or signal number. | ||
+ | |||
+ | === I have received a signal. Now what? === | ||
+ | |||
+ | When a signal has been received by the script, the script can do one of three actions: | ||
+ | * Ignore it and do nothing. This is probably what most scripts do without the script authors realising it. | ||
+ | * Catch the signal using trap and take appropriate action. | ||
+ | * Take the default action. | ||
+ | |||
+ | All the above is true except for the following signals: | ||
+ | * SIGKILL (signal 9) | ||
+ | * SIGSTOP(signal 17) | ||
+ | * SIGCONT (signal 19) |