BASH

http://talk.jpnc.info/bash_lfnw_2017.pdf

Make newlines the only separator:

IFS=$'\n'

Do something on exit (even if error):

function cleanup() {
        # do something
}

trap cleanup EXIT

Functions boolean returns:

# 1st variant
isdirectory() {
  if [ -d "$1" ]; then
    return 0
  else
    return 1
  fi
}

# 2nd variant
isdirectory() {
  if [ -d "$1" ]; then
    true
  else
    false
  fi
}

# 3rd variant
isdirectory() {
  [ -d "$1" ]
}

# USING
if isdirectory $1; then
    echo "is directory"
else
    echo "nopes"
fi

Multiple arguments passing:

ARGS=$@
# ./script.sh "one two three"
# 1. one
# 2. two
# 3. three

ARGS="$@"
# ./script.sh "one two three"
# 1. one two three

Operators:

let "var += 5"
let "var = 5 - 3"

Asynchronous bash script:

mycommand &
child_pid=$!

while kill -0 $child_pid >/dev/null 2>&1; do
    echo "Child process is still running"
    sleep 1
done

echo "Child process has finished"

Parsing script arguments:

#!/bin/sh
# Keeping options in alphabetical order makes it easy to add more.

while :
do
    case "$1" in
      -f | --file)
          file="$2"     # You may want to check validity of $2
          shift 2
          ;;

      -h | --help)
          display_help  # Call your function
          exit 0
          ;;

      -v | --verbose)
          verbose="verbose"
          shift
          ;;

      --)           # End of all options
          shift
          break;

      -*)
          echo "Error: Unknown option: $1" >&2
          exit 1
          ;;

      *)            # No more options
          break
          ;;
    esac
done

Async/sync mode. Add ‘async=true’ before run script:

COMMAND="uptime"
SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
VMS_IPS="192.168.1.1 192.168.1.2"
CHILD_PIDS=""

VM_NUM=0

for VM_IP in $VMS_IPS; do

        (( VM_NUM++ ))

        if [ "$async" == "true" ]; then
                ssh root@$VM_IP "$COMMAND" >> $SCRIPT_PATH/temp.$VM_NUM 2>&1 &
                CHILD_PIDS="$CHILD_PIDS $!"
        else
                ssh $SSH_USER@$VM_IP "$COMMAND"
        fi
done

if [ "$async" == "true" ]; then
        for CHILD_PID in $CHILD_PIDS; do
                while kill -0 $CHILD_PID >/dev/null 2>&1; do
                        echo "Processing in asynchronous mode..."
                        sleep 5.0
                done
        done

        cat $(ls -v temp.*)
        rm temp.*
fi

Check is program exists:

if hash <program> 2>/dev/null; then
    echo "exists"
else
    echo "not exists"
fi

Add zeros before number:

VAR=15
echo "$(seq -f %03g $VAR $VAR)"
# 015

BASH if grep ixists statement:

if grep --quiet 'text' /path/to/file; then
  echo exists
else
  echo not found
fi

Get path to script which run:

SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Bash get last line from a variable:

echo "${VAR##*$'\n'}"

Is file exist:

if [ ! -f /tmp/foo.txt ]; then
    echo "File not found!"
fi

Functions on BASH:

#!/bin/sh

# this will fail because foo has not been declared yet.
myFunction parameter_1 parameter_2

[function] myFunction() {
    echo "Parameters: $1 $2"
}

# this will work
myFunction parameter_1 parameter_2

Do while with iterator:

COUNT=0

while [ $COUNT -lt 10 ]
do
        (( COUNT++ ))
        echo $COUNT
done

Boolean in BASH:

VAR=true

if [ "$VAR" = true ] ; then
    echo 'true'
fi

Check if a variable is set:

if [ -z ${var+x} ]; then
    echo "var is unset"
else
    echo "var is set to '$var'"
fi

# this will return true if a variable is unset or set to the empty string ("")
if [ -z "$VAR" ];

For in bash:

for i in $( ls ) ; do
  rm -R $i
done

Multiline file creating:

    cat > /path/to/file <<EOF
    line 1
    line 2
    EOF

# with sudo
sudo bash -c "cat > /path/to/file" << EOF
line1
line2
EOF

Make sure only root can run our script:

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

Stdout/stderr redirects:

# Both threads (stdout/stderr) will be redirected to a file
<command> >file 2>&1

# Stdout to file. Stderr to terminal
<command> 2>&1 >file

Logical operators for if-then-else-fi construction:

-z $VAR         # string is empty
-n $VAR         # string isn't empty

$VAR =/== $VAR  # strings are equal
$VAR != $VAR    # strings aren't equal

-eq             # equal
-ne             # not equal

-lt(<)          # less
-le(<=)         # less or equal

-gt(>)          # more
-ge(>=)         # more or equal

!               # logical not
-a(&&)          # logical and
-o(||)          # logical or

-e <file>       # file exists
-d <file>       # file exists and is a directory
-f <file>       # is a regular file (not a directory or device file)
-b <file>       # file is a block device
-w <file>       # file exists and the write permission is granted
-x <file>       # file exists and the execute permission is granted
-r <file>       # file exists and the read permission is granted
-s <file>       # file exists and it's size is greater than zero (ie. it is not empty)

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html

https://www.opennet.ru/docs/RUS/bash/bash-4.html

Positional parameters

$* $1 $2 $3 … ${N}
$@ $1 $2 $3 … ${N}
“$*” “$1c$2c$3c…c${N}”
“$@” “$1” “$2” “$3” … “${N}”

set

set [abefhkmnptuvxldCHP] [-o опция] [аргумент]:

-a | allexport      отмечает переменные, которые модифицированы или созданы для зкспорта.

-b | notify вызывает прекращение фоновых заданий, о котором сообщает перед выводом следующего базового приглашения.

-е | errexit немедленный выход, если выходное состояние команды ненулевое.

-f | noglob выключает генерацию имени файла (глоббирование).

-h  обнаруживает и запоминает (хеширует) команды как определенные функции до того, как функция будет выполнена.

-к  В окружении команды располагаются все аргументы ключевых слов, не только те, которые предшествуют имени команды.

-m | monitor        Разрешается управление заданиями (см. главу 5).

-n | noexec Читает команды, но не выполняет их.

-о имя_опции        Устанавливает флаг, соответствующий имени_опции.

braceexpand оболочка должна выполнить brace-расширение (см. раздел 2.2).

emacs       использует интерфейс редактирования emacs (см. главу 7 "Редактирование командной строки").


ignoreeof   оболочка не выходит при чтении EOF.

interactive-comments        позволяет вызывать слово, начинающееся с '#', и все оставшиеся символы на этой строке игнорировать в диа логовой оболочке.

posix       изменяет режим Bash в соответствии со стандартом Posix 1003.2, когда операция по умолчанию отличается от него. Предназначен для того, чтобы сделать режим строго подчиненным зтому стандарту.

vi  использует интерфейс редактирования строки редактора vi.

-p | privileged     Включает привилегированный режим. В зтом режиме файл $ENV не выполняется, и функции оболочки не наследуются из среды. Зто включается автоматически начальными действиями, если идентификатор зффективного пользователя (группы) не равен идентификатору реального пользователя (группы). Выключение зтой опции присваивает идентификатор зффективного пользователя (группы) идентификатору реального пользователя (группы).

-t  выход после чтения и выполнения команды.

-u | nounset        во время замещения рассматривает незаданную переменную как ошибку.

-v | verbose        выдает строки ввода оболочки по мере их считывания.

-x | xtrace выводит команды и их аргументы по мере выполнения команд.

-l  сохраняет и восстанавливает связывание имени в команде for.

-d | nohash Выключает хеширование команд, найденных для выполнения. Обычно команды запоминаются в хеш-таблице и, будучи однажды найденными, больше не ищутся.

-С | noclobber не позволяет существующим файлам перенаправление вывода.

-Н | histexpand     закрывает замену стиля ! истории. Этот флаг принимается по умолчанию.

-Р | physical       Если установлена, не следует символьному указателю при выполнении команды типа cd, которая изменяет текущий каталог. Вместо этого используется физический каталог.

--  Если нет аргументов, следующих за зтим флагом, то не задаются позиционные параметры. В противном случае позиционные параметры присваиваются аргументам, даже если некоторые из них начинаются с а-.

-   Сигнал конца опции, вызывающей присваивание оставшихся аргументов позиционным параметрам. Опции -x и -v выключаются. Если здесь нет аргументов, позиционный параметр не изменяется.

При использовании + вместо - осуществляется выключение зтих флагов. Флаги также могут использоваться при вызове оболочки. Текущий набор флагов можно найти в $-. Оставшиеся N переменных - позиционные параметры и присваиваются по порядку $1, $2,...,$N. Если аргументы не даны, выводятся все переменные оболочки.