bash: как распространять ошибки при подстановке процессов?

Проверьте содержание /etc/network/interfaces. При использовании DHCP он должен быть указан там. Можно отсутствовать auto пункт для автоматического запуска сети. Документация может быть просмотрена с командой man interfaces.

Этот файл может также использоваться для установки фиксированного IP-адреса. Поскольку это - веб-сервер, необходимо использовать фиксированный IP-адрес, а не динамический адрес от DHCP. Это возможно сеть, с которой Вы соединяетесь, не имеет сервера DHCP.

Можно перезапустить интерфейс с помощью команд ifdown eth0 сопровождаемый ifup eth0. Вывод dmesg после того, как это может дать подсказку относительно того, какова проблема.

Команда ps -ef | grep dhc должен показать, есть ли у Вас выполнение процесса клиента DHCP. Это не установит адрес, если не будет сервер DHCP в сети, с которой Вы соединяетесь.

19
22.07.2015, 15:30
5 ответов

Эту проблему можно было обойти, например:

cat <(false || kill $$) <(echo ok)
other_command

Подоболочка скрипта SIGTERM d перед вторым команда может быть выполнена ( другая_команда ). Команда echo ok выполняется «иногда»: Проблема в том, что подстановки процессов являются асинхронными. Нет гарантии, что команда kill $$ будет выполнена до или после команды echo ok . Это вопрос расписания операционной системы.

Рассмотрим сценарий bash, подобный этому:

#!/bin/bash
set -e
set -o pipefail
cat <(echo pre) <(false || kill $$) <(echo post)
echo "you will never see this"

Результатом этого сценария может быть:

$ ./script
Terminated
$ echo $?
143           # it's 128 + 15 (signal number of SIGTERM)

Или:

$ ./script
Terminated
$ pre
post

$ echo $?
143

Вы можете попробовать, и после нескольких попыток вы увидите два разных порядка на выходе. В первом сценарий был завершен до того, как две другие команды echo смогли записать в файловый дескриптор. Во втором случае команда false или kill , вероятно, была запланирована после команд echo .

Или, точнее, был запланирован системный вызов signal () утилиты kill , которая отправляет сигнал SIGTERM процессу оболочки ( или был доставлен) позже или раньше, чем системный вызов echo write () .

Однако сценарий останавливается, и код выхода не равен 0. Следовательно, это должно решить вашу проблему.

Другое решение - это, конечно, использование для этого именованных каналов. Но это зависит от вашего скрипта, насколько сложно будет реализовать именованные каналы или обходной путь, описанный выше.

Ссылки:

6
27.01.2020, 19:45

Для записи, и даже если ответы и комментарии были хорошими и полезными, я закончил реализацию чего-то немного другого (у меня были некоторые ограничения на прием сигналов в родительском процессе, о которых я не упомянул в вопросе)

В основном, я закончил делать что-то вроде этого:

command <(subcomand 2>error_file && rm error_file) <(....) ...

Тогда я проверяю файл ошибок. Если он существует, то я знаю, какая подкоманда провалилась (и содержимое файла error_file может быть полезным). Более многословная и хакерская, которую я изначально хотел, но менее громоздкая, чем создание именованных труб в однословной бэш-команде.

2
27.01.2020, 19:45

В этом примере показано, как использовать killвместе с trap.

#! /bin/bash
failure ()
{
  echo 'sub process failed' >&2
  exit 1
}
trap failure SIGUSR1
cat < <( false || kill -SIGUSR1 $$ )

Но killне может передать код возврата из вашего подпроцесса в родительский процесс.

3
27.01.2020, 19:45

Подобно тому, как вы реализовали бы $PIPESTATUS/ $pipestatusс оболочкой POSIX, которая ее не поддерживает , вы можете получить статус выхода команд, передав их через труба:

unset -v false_status echo_status
{ code=$(
    exec 3>&1 >&4 4>&-
    cat 3>&- <(false 3>&-; echo >&3 "false_status=$?") \
             <(echo ok 3>&-; echo >&3 "echo_status=$?")
);} 4>&1
cat_status=$?
eval "$code"
printf '%s_code=%d\n' cat   "$cat_status" \
                      false "$false_status" \
                      echo  "$echo_status"

Что дает:

ok
cat_code=0
false_code=1
echo_code=0

Или вы можете использовать pipefailи реализовать подстановку процессов вручную, как если бы вы использовали оболочки, которые ее не поддерживают:

set -o pipefail
{
  false <&5 5<&- | {
    echo OK <&5 5<&- | {
      cat /dev/fd/3 /dev/fd/4
    } 4<&0 <&5 5<&-
  } 3<&0
} 5<&0
2
27.01.2020, 19:45

Самый надежный способ, который я нашел, это сохранить код ошибки подпроцесса во временном файле, например, в контексте функции:

function() {
  ERR=$(mktemp)
  VAR=$(some_command; echo $? > $ERR)
  if [[ $(cat $ERR && rm $ERR) -gt 0 ]]; then
    echo "An error occurred in the sub shell" > /dev/stderr
    return 1
  fi
}
1
04.09.2020, 12:42

Теги

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