Этот вопрос уже был отвечен/решен, но я хотел упомянуть нечетную вещь, которая произошла с нами однажды: сервер не включил бы после сбоя питания.
Мы продвинули бы кнопку питания, но ничего не произойдет. Мы имели идентичную запчасть в наличии, таким образом, мы попробовали источник питания, но это не работало. Мы помещаем жесткий диск от мертвого поля в запчасти (и подкачанные источники питания назад), и это было прекрасно.
НО, оригинал имел второй NIC, таким образом, мы должны были переместить это также и когда мы сделали, новое поле не включит. Этой точкой мы делали все тесты с покрытиями прочь, таким образом, мы видели, что, когда мы продвинули выключатель питания, вентилятор будет дергаться, и nic свет питания продвинулся бы, но вот именно. Таким образом, мы откопали запчасть для второго nic, и все было хорошо.
Я обычно помещал что-то подобное следующему в начале каждого сценария (особенно, если это будет работать как демон):
#!/bin/bash
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>log.out 2>&1
# Everything below will go to the file 'log.out':
Объяснение:
exec 3>&1 4>&2
Сохраняет дескрипторы файлов, таким образом, они могут быть восстановлены тому, чем они были перед перенаправлением или использовали себя для вывода, к чему они были перед следующим перенаправлением.
trap 'exec 2>&4 1>&3' 0 1 2 3
Восстановите дескрипторы файлов для конкретных сигналов. Не обычно необходимый, так как они должны быть восстановлены, когда подоболочка выходит.
exec 1>log.out 2>&1
Перенаправление stdout
в файл log.out
затем перенаправление stderr
кому: stdout
. Обратите внимание, что порядок важен, когда Вы хотите их идущий в тот же файл. stdout
должен быть перенаправлен прежде stderr
перенаправляется к stdout
.
С тех пор, для наблюдения вывода на консоли (возможно), можно просто перенаправить к &3
. Например,
echo "$(date) : part 1 - start" >&3
перейдет в везде, где stdout
был направлен, по-видимому, консоль, до выполняющейся строки 3 выше.
для получения вывода ssh к файлу журнала необходимо перенаправить stderr
кому: stdout
. можно сделать это путем добавления 2>&1
после Вашего сценария удара.
это должно быть похожим на это:
#!/bin/bash
(
...
) 2>&1 | tee ...
когда это не отобразит сообщения в правильном порядке, попытайтесь добавить другую подоболочку:
#!/bin/bash
((
...
) 2>&1) | tee ...
Когда я считал Ваш вопрос, Вы не хотите регистрировать вывод, но вся последовательность команд, в этом случае, другие ответы не помогут Вам.
Вызовите сценарии оболочки с-x для вывода всего:
sh -x foo.sh
Журнал в файл Вы хотите с:
sh -x foo.sh >> /home/scripts/cron/logs
В ударе можно поместить set -x
и это распечатает от каждой команды, которую это выполняет (и переменные удара) после этого. Можно выключить его с set +x
.
Если Вы хотите быть параноиками, можно поместить set -o errexit
в Вашем сценарии. Это означает, что сценарий перестанет работать и остановится, если одна команда возвратила ненулевой код выхода, который является стандартом Unix способ сигнализировать, что что-то пошло не так, как надо.
Если Вы хотите получить более хорошие журналы, необходимо посмотреть на ts
в moreutils
пакет debian/ubuntu. Это снабдит префиксом каждую строку метку времени и распечатает его. Таким образом, Вы видите, когда вещи происходили.
Исходя из того, что говорили другие, руководство по набору является хорошим ресурсом. Я помещаю:
#!/usr/bin/env bash
exec 1> command.log 2>&1
set -x
В начало сценариев, которые я хочу продолжить, или устанавливаю -ex
, если он должен завершиться в случае ошибки.
TL;DR - Вчера я написал набор инструментов для ведения журнала запусков программ и сессий.
В настоящее время доступен по адресу https://github.com/wwalker/quick-log
Как администратор, я всегда хочу регистрировать выходные данные какой-либо команды, часто не скрипта. Чтобы решить эту проблему, я написал несколько вещей. Проще всего использовать программный «скрипт», как упоминалось xX0v0Xx. Я обнаружил, что вызов скрипта (без каких-либо аргументов) часто приводит к тому, что я перезаписываю выходные данные предыдущего скрипта. Поэтому я создал этот псевдоним. Все, что он делает, это предотвращает перезапись. Вам нужен каталог ~/tmp.
$ alias scr='script ~/tmp/typescript-$(date +%FT%T)'
$ scr
Script started, file is /home/wwalker/tmp/typescript-2019-12-05T18:56:31
$
Это здорово, когда я хочу поймать интерактивную сессию.
Когда я хочу записать в журнал выходные данные команды (скрипта или двоичного файла), мне либо нужен точный вывод, либо я хочу выходные данные с метками времени перед каждой строкой. Итак, я написал эти две функции bash:
alias iso8601="date +%Y-%m-%dT%H:%M:%S"
justlog(){
name=$(basename "$1")
log=~/logs/${name}-$(iso8601)
"$@" > "$log" 2>&1
}
timelog(){
name=$(basename "$1")
log=~/logs/${name}-$(iso8601)
# https://github.com/wwalker/ilts
# You could replace ilts with ts
# /usr/bin/ts %FT%H:%M:%.S
"$@" |& ilts -S -E > "$log" 2>&1
}
Просто выполните команду, как обычно:
justlog run rcn rcn-work\\\\\* 'ps -ef -o lstart,cmd | grep [s]upervisor'
или
timelog run rcn rcn-work\\\\\* 'ps -ef -o lstart,cmd | grep [s]upervisor'
Это только что создало 2 файла с именем:
wwalker@polonium:~ ✓ $ ls -l ~/logs/run*
-rw-r--r-- 1 wwalker wwalker 10495 2019-12-05 18:21:14.985 /home/wwalker/logs/run-2019-12-05T18:21:13
-rw-r--r-- 1 wwalker wwalker 1694 2019-12-05 18:24:02.878 /home/wwalker/logs/run-2019-12-05T18:24:01
-rw-r--r-- 1 wwalker wwalker 7623 2019-12-05 18:25:07.873 /home/wwalker/logs/run-2019-12-05T18:25:06
-rw-r--r-- 1 wwalker wwalker 10296 2019-12-05 18:34:59.546 /home/wwalker/logs/run-2019-12-05T18:34:57
Но, подождите, есть еще!!
Я не хотел делать ls, чтобы найти имя файла журнала, который justlog или timelog только что создали для меня. Итак, я добавил еще 3 функции:
newestlog(){
name=$(basename "$1")
ls ~/logs/"${name}"* | tail -1
}
viewlog(){
name=$(basename "$1")
view $( newestlog "$name" )
}
lesslog(){
name=$(basename "$1")
less $( newestlog "$name" )
}
Итак, вы запускаете свою команду с justlog (или timelog), а затем просто используете lesslog или viewlog (я, вероятно, создам журнал emacs для этих людей):
justlog run rcn rcn-work\\\\\* 'ps -ef -o lstart,cmd | grep [s]upervisor'
lesslog run
Вот и все, нет ls ~/tmp
, нет игр для завершения вкладок, чтобы найти имя файла. Просто запустите lesslog (или viewlog, если вам нравится использовать vim для просмотра журналов).
Но, подождите! Там больше!
"Я все время использую grep в своих файлах журналов" - И ответ, как вы уже догадались, greplog
Во-первых, получите текст из всех файлов сервера 800 /etc/cron.d/atop, которые сломаны:
justlog fordcrun 'cat /etc/cron.d/atop; md5dum /etc/cron.d/atop'
Затем получите имена хостов (в строке над выводом в файл :-) ) с помощью greplog:
wwalker@polonium:~ ✓ $ greplog fordcrun -B1 -F "0 0 * * root"
int-salt-01:
0 0 * * root systemctl restart atop
--
rcn-pg-01:
0 0 * * root systemctl restart atop
rcn-pg-02:
0 0 * * root systemctl restart atop
rcn-pg-03:
0 0 * * root systemctl restart atop
Я обнаружил, что ответа @nicerobot (Как я могу полностью регистрировать все действия bash-скриптов? ) может быть недостаточно для полного перенаправления весь вывод на консоль. Некоторые выходные данные все еще могут быть потеряны.
Полное перенаправление выглядит следующим образом:
#!/bin/bash
# some basic initialization steps including `NEST_LVL` and `SCRIPTS_LOGS_ROOT variables...
source ".../__myinit__.sh"
# no local logging if nested call
(( ! IMPL_MODE && ! NEST_LVL )) && {
export IMPL_MODE=1
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' EXIT HUP INT QUIT RETURN
[[ ! -e "${SCRIPTS_LOGS_ROOT}/.log" ]] && mkdir "${SCRIPTS_LOGS_ROOT}/.log"
# RANDOM instead of milliseconds
case $BASH_VERSION in
# < 4.2
[123].* | 4.[01] | 4.0* | 4.1[^0-9]*)
LOG_FILE_NAME_SUFFIX=$(date "+%Y'%m'%d_%H'%M'%S''")$(( RANDOM % 1000 ))
;;
# >= 4.2
*)
printf -v LOG_FILE_NAME_SUFFIX "%(%Y'%m'%d_%H'%M'%S'')T$(( RANDOM % 1000 ))" -1
;;
esac
(
(
myfoo1
#...
myfooN
# self script reentrance...
exec $0 "$@"
) | tee -a "${SCRIPTS_LOGS_ROOT}/.log/${LOG_FILE_NAME_SUFFIX}.myscript.log" 2>&1
) 1>&3 2>&4
exit $?
}
(( NEST_LVL++ ))
# usual script body goes here...
Объяснение:
echo
как на консоль, так и на в файл, поэтому единственный способ разделить выходной поток — это соединение «труба плюс тройник». (...)
либо для перенаправления каждого потока в отдельный файл, либо для восстановления всех потоков обратно в исходное состояние отдельными шагами. Вторая причина заключается в том, что вызовы myfoo
перед повторным входом должны работать как есть без какого-либо дополнительного перенаправления. NEST_LVL
для указания уровня вложенного вызова. IMPL_MODE
. Вы можете просто использовать "сценарий".
man-скрипт
для подробностей.
Пример:
script -a -e -c "set -x; echo this is logging ..; <your script can be called here>" mylogfile.log