Как я могу полностью зарегистрировать все действия сценариев удара?

Этот вопрос уже был отвечен/решен, но я хотел упомянуть нечетную вещь, которая произошла с нами однажды: сервер не включил бы после сбоя питания.

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

НО, оригинал имел второй NIC, таким образом, мы должны были переместить это также и когда мы сделали, новое поле не включит. Этой точкой мы делали все тесты с покрытиями прочь, таким образом, мы видели, что, когда мы продвинули выключатель питания, вентилятор будет дергаться, и nic свет питания продвинулся бы, но вот именно. Таким образом, мы откопали запчасть для второго nic, и все было хорошо.

45
задан 19 April 2017 в 18:21
8 ответов

Я обычно помещал что-то подобное следующему в начале каждого сценария (особенно, если это будет работать как демон):

#!/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':

Объяснение:

  1. exec 3>&1 4>&2

    Сохраняет дескрипторы файлов, таким образом, они могут быть восстановлены тому, чем они были перед перенаправлением или использовали себя для вывода, к чему они были перед следующим перенаправлением.

  2. trap 'exec 2>&4 1>&3' 0 1 2 3

    Восстановите дескрипторы файлов для конкретных сигналов. Не обычно необходимый, так как они должны быть восстановлены, когда подоболочка выходит.

  3. exec 1>log.out 2>&1

    Перенаправление stdout в файл log.out затем перенаправление stderr кому: stdout. Обратите внимание, что порядок важен, когда Вы хотите их идущий в тот же файл. stdout должен быть перенаправлен прежде stderr перенаправляется к stdout.

С тех пор, для наблюдения вывода на консоли (возможно), можно просто перенаправить к &3. Например,

echo "$(date) : part 1 - start" >&3

перейдет в везде, где stdout был направлен, по-видимому, консоль, до выполняющейся строки 3 выше.

68
ответ дан 28 November 2019 в 19:40

для получения вывода ssh к файлу журнала необходимо перенаправить stderr кому: stdout. можно сделать это путем добавления 2>&1 после Вашего сценария удара.

это должно быть похожим на это:

#!/bin/bash
(
...
) 2>&1 | tee ...

когда это не отобразит сообщения в правильном порядке, попытайтесь добавить другую подоболочку:

#!/bin/bash
((
...
) 2>&1) | tee ...
14
ответ дан 28 November 2019 в 19:40

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

Вызовите сценарии оболочки с-x для вывода всего:

sh -x foo.sh

Журнал в файл Вы хотите с:

sh -x foo.sh >> /home/scripts/cron/logs

13
ответ дан 28 November 2019 в 19:40

В ударе можно поместить set -x и это распечатает от каждой команды, которую это выполняет (и переменные удара) после этого. Можно выключить его с set +x.

Если Вы хотите быть параноиками, можно поместить set -o errexit в Вашем сценарии. Это означает, что сценарий перестанет работать и остановится, если одна команда возвратила ненулевой код выхода, который является стандартом Unix способ сигнализировать, что что-то пошло не так, как надо.

Если Вы хотите получить более хорошие журналы, необходимо посмотреть на ts в moreutils пакет debian/ubuntu. Это снабдит префиксом каждую строку метку времени и распечатает его. Таким образом, Вы видите, когда вещи происходили.

10
ответ дан 28 November 2019 в 19:40

Исходя из того, что говорили другие, руководство по набору является хорошим ресурсом. Я помещаю:

#!/usr/bin/env bash
exec 1> command.log 2>&1
set -x

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

0
ответ дан 28 November 2019 в 19:40

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
0
ответ дан 6 December 2019 в 00:29

Я обнаружил, что ответа @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...

Объяснение:

  1. Недостаточно просто перенаправить вывод, потому что вам еще нужно перенаправить внутренние вызовы echo как на консоль, так и на в файл, поэтому единственный способ разделить выходной поток — это соединение «труба плюс тройник».
  2. Мы должны использовать оператор (...) либо для перенаправления каждого потока в отдельный файл, либо для восстановления всех потоков обратно в исходное состояние отдельными шагами. Вторая причина заключается в том, что вызовы myfoo перед повторным входом должны работать как есть без какого-либо дополнительного перенаправления.
  3. Поскольку скрипт может быть вызван из вложенного скрипта, нам нужно перенаправить вывод в файл только один раз при вызове верхнего уровня. Поэтому мы используем переменную NEST_LVL для указания уровня вложенного вызова.
  4. Поскольку перенаправление может быть выполнено извне, независимо от скрипта, мы должны явно включить внутреннее перенаправление с помощью переменной IMPL_MODE.
  5. Мы должны использовать значения даты и времени для автоматического создания нового уникального файла журнала при каждом запуске скрипта.
2
ответ дан 6 February 2020 в 09:04

Вы можете просто использовать "сценарий".

man-скрипт для подробностей.

Пример:

script -a -e -c "set -x; echo this is logging ..; <your script can be called here>" mylogfile.log
0
ответ дан 29 July 2020 в 06:07

Теги

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