8

Я пытаюсь получить дату последнего изменения файла с помощью этой команды

TM_LOCAL=`ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'`

TM_LOCAL имеет значение типа «2012-05-16 23:18» после выполнения этой строки

Я также хотел бы проверить PIPESTATUS, чтобы увидеть, если была ошибка. Например, если файл не существует, ls возвращает 2. Но $? имеет значение 0, поскольку имеет возвращаемое значение awk .

Если я запускаю эту команду в одиночку, я могу проверить возвращаемое значение ls, посмотрев на ${PIPESTATUS[0]}

ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'

Но $PIPESTATUS не работает так, как я ожидал, если назначить вывод переменной, как в первом примере. В этом случае массив $PIPESTATUS имеет только 1 элемент, который совпадает с $?

Итак, вопрос в том, как я могу получить и $PIPESTATUS и назначить вывод переменной одновременно?

6 ответов6

7

Вы могли бы сделать это:

TM_LOCAL=$(ls -l --time-style=long-iso ~/.vimrc | \
             awk '{ print $6" "$7 }' ; exit ${PIPESTATUS[0]} )

Тогда $? будет код возврата от ls . Это не работает, если вам нужен код возврата более чем из одной части канала (но вы можете разделить конвейер, если выходные данные не слишком велики, как здесь).

Вот довольно дорогой способ получения полного массива PIPESTATUS и вывода. Не очень элегантно, но больше ничего не нашел:

result=$(echo -e "a\nb\nc" | \
          ( cat ; exit 1 ) | \
          ( cat ; exit 42 ) ; echo ${PIPESTATUS[@]})
output=$(head -n -1 <<< "$result")
status=($(tail -n 1 <<< "$result"))
echo "Output:"
echo "$output"
echo "Results:"
echo "${status[@]}"

Который дает:

Output:
a
b
c
Results:
0 1 42
3

Я предполагаю, что проблема в том, что PIPESTATUS полностью исчезает, как только вы выполняете команду. Вы можете получить полный массив PIPESTATUS в bash версии 2 или выше:

declare -a status
status=(${PIPESTATUS[@]})

Затем получите доступ к ${status[0]} , ${status[1]} и т.д.

3

Используйте set -o pipefail в bash чтобы получить самый правый ненулевой код завершения в поточной последовательности команд как $? , От man bash:

Если установлено, возвращаемое значение конвейера - это значение последней (самой правой) команды для выхода с ненулевым статусом или ноль, если все команды в конвейере завершаются успешно. Эта опция по умолчанию отключена.

Тогда вы можете просто получить доступ к $? , Используйте set +o pipefail чтобы снова отключить.

2

Основная проблема с "что вы ожидаете" заключается в том, что команда в обратных кавычках выполняется в подоболочке; $PIPESTATUS существует там, и статус, возвращаемый из m, следует тем же правилам, что и при выполнении одного исполняемого файла (или сценария оболочки). Статус команды backquote является самым правым (awk) статусом.

Чтобы реализовать то, что сказал @ Daniel Beck , установите параметр pipefail в подоболочке следующим образом:

TM_LOCAL=`set -o pipefail; ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'` теперь статус сохраняется в $? после этого будет статус ls (если не ноль).

Тем не менее, я думаю, что явный if [ -f ~/.vimrc ]; ... тест был бы более читабельным.

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

0

Один из вариантов - проверить наличие вашего файла перед тем, как получить время его изменения с вызовом stat . Так как stat возвращает немного больше, чем вы хотите в метке времени, вы можете обрезать его, используя расширение параметра

[[ -f ~/.vimrc ]] && TM_LOCAL=$(stat -c '&y' ~/.vimrc 2>/dev/null)
TM_LOCAL=${TM_LOCAL%:*}  # Safe to do, even if stat fails
0

Я хотел отправить электронное письмо от fron cron, только если статус выхода не был нулевым

Хитрость заключается в том, что для получения stdin для конца конвейера вам нужно поместить его в подоболочку - но это, кажется, скрывает значение PIPESTATUS ...

тестовый крон выплевывает некоторые выходные данные и выходит с 1 или 0 ..

./testcron | (test ${PIPESTATUS[0]} -ne 0 || mail -s "testcron output" paul)

ОБНОВЛЕНИЕ: PIPESTATUS не виден, пока команда конвейера не обработана

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .