Последовательное перечисление устройств Linux

Вы можете добавить ловушку на EXIT, которая убивает все процессы в вашем сеансе:

(чтобы добавить в ваш .bashrc ):

killall_on_exit() {
  sid=$(ps -o sid= -p "$$")
  if [ "$sid" -eq "$$" ]; then
    # we're the session leader
    (
      trap '' TERM
      ps -eo pgid= -o sid= |
        awk -v sid="$sid" '$2 == sid && !seen[$1]++ {print "-" $1}' |
        xargs kill -s TERM --
    )
  fi
}
trap killall_on_exit EXIT

Это убивает все группы процессов в вашем сеансе. Это не убьет процессы, которые запускаются в новом сеансе, но поскольку новые сеансы обычно запускаются эмуляторами терминала, если вы уберете эмулятор терминала, скорее всего, процесс, который он порождает, также умрет (и его дочерние элементы, если лидер интерактивный bash с той же ловушкой).

nohup или disown обычно не делают команды невосприимчивыми к этому.

Вы можете заменить приведенные выше TERM на HUP , но тогда обратите внимание, что некоторые команды, такие как xterm , игнорируют SIGHUP.

Чтобы иммунизировать команду от SIGTERM, запустите ее как:

(trap '' TERM; emacs &)
1
20.03.2019, 09:58
3 ответа

После дополнительного тестирования я пришел к выводу, что этот переключатель кода имеет красивую оболочку и возвращает код возврата выполненной команды. Код, который опубликовал @Freddy, почти завершен. Код возврата экспортируется внутрь функции, но не за ее пределы.

Использование shopt -s lastpipe было взято с этой страницы:Запись часто задаваемых вопросов Bash #24 :«Я устанавливаю переменные в цикле. Почему они внезапно исчезают после завершения цикла? Или, почему я не могу передать данные для чтения?"

Вот окончательное рабочее решение:

#!/bin/bash

log_path_file="./logs/test.log"
exe_cmd()
{
    echo "`date +%Y-%m-%d---%r` [Info]: Command to execute: $@"  | tee -a ${log_path_file};
    echo ""  | tee -a ${log_path_file};
    echo ""  | tee -a ${log_path_file};

    set +m
    shopt -s lastpipe

    cmdResult=0
    {
            "$@"
            returncode=$?
            # save result code
            cmdResult=${returncode}

            if [ "$returncode" -eq 0 ]; then
              echo "`date +%Y-%m-%d---%r` [Info]: successfully executed \"$@\""
            else
              echo "`date +%Y-%m-%d---%r` [Info]: failed to execute \"$@\", exit code: ${returncode}"
            fi
    } 2>&1 | tee -a "$log_path_file"

    echo "`date +%Y-%m-%d---%r` [Info]: cmdResult result ${#cmdResult[@]}"

    return ${#cmdResult[@]};
}

cmd="scp some_user@$some_host:some_path/* a_local_path/sub_path";
exe_cmd ${cmd}
returncode=$?
echo "`date +%Y-%m-%d---%r` [Info]: scp execution result: ${returncode}"  | tee -a ${log_path_file};
0
27.01.2020, 23:41

В данном конкретном случае было бы проще просто выполнить ls -lи действовать непосредственно на его статус выхода:

if ls -l "$local_path"; then
    echo 'success'
else
    printf 'failure (code %d)\n' "$?"
fi | tee -a "$log_path_file"

В оболочке bashвы также можете исследовать значения в массиве PIPESTATUS:

$ false | true | true | false | false
$ printf '%s\n' "${PIPESTATUS[@]}"
1
0
0
1
1

В вашем случае:

ls -l "$local_path" | tee -a "$log_path_file"

ls_status=${PIPESTATUS[0]}
if [ "$ls_status" -eq 0 ]; then
    echo 'success'
else
    printf 'failure (code %d)\n' "$ls_status"
fi | tee -a "$log_path_file"
4
27.01.2020, 23:41

Вы можете использовать функцию, которая принимает команду в качестве аргументов и teeвыводит (stdout и stderr )в файл журнала.

local_path="~/njn"
log_path_file="test.log"

function log_cmd ()
{
        {
                "$@"
                returncode=$?
                if [ "$returncode" -eq 0 ]; then
                  echo "[successfully executed \"$@\"]"
                else
                  echo "[failed to execute \"$@\", exit code: ${returncode}]"
                fi
                return $returncode

        } 2>&1 | tee -a "$log_path_file"
        # return exit code of first command in pipeline
        return ${PIPESTATUS[0]}
}

log_cmd ls -l "$local_path"
log_cmd echo "hello world"
0
27.01.2020, 23:41

Теги

Похожие вопросы