Как отследить bash-скрипт - выход из состояния и почему он не удался
Иногда мне нужно выполнить команду следующим образом:
cat file.txt | awk ' NR%4 == 2 { print $1 }' | sort | uniq -c | sort -gr >>output.txt &
поверх больших файлов (размером от 2 до 32 ГБ). Я запускаю команду вечером, а когда я прихожу утром, output.txt иногда пуст, и процесс больше не выполняется.
Пожалуйста, как я могу отследить, что происходит? Почему и когда моя команда провалилась? Я знаю, что конвейер работает, потому что иногда он просто успешно завершается.
Большое спасибо!
ОБНОВЛЕНИЕ: я теперь думаю, что мой процесс был убит, потому что сервер, когда я выполняю эти вычисления, рекомендуется только для интерактивного использования. Если это правда, единственное, что я могу видеть из файла журнала, это то, что он не был успешным - не закончен.
Есть ли способ узнать, что мой процесс действительно был убит? Благодарю.
3 ответа
Первый шаг, инкапсулируйте этот скрипт в файл, а не запускайте его непосредственно в терминале (и потеряйте награду UUOC, пока мы на нем).
#!/bin/bash
{
awk 'NR%4 == 2 { print $1 }' file.txt | sort | uniq -c | sort -gr >>output.txt
} 2>error.log
Это захватывает все сообщения об ошибках в файле error.log
, Затем вы можете добавить диагностическую информацию.
#!/bin/bash
{
date >&2
set -x
awk 'NR%4 == 2 { print $1 }' file.txt | sort | uniq -c | sort -gr >>output.txt
date >&2
} 2>error.log
Теперь у вас есть информация о том, когда и когда это началось и когда это закончилось. Так как ты в bash
вы можете организовать захват состояний выхода каждого процесса в конвейере, если хотите, чтобы вы точно знали, какие команды вышли с каким состоянием. Вы можете или не можете получать сообщения о том, какой процесс был убит (если процесс был убит внешним сигналом), но если процесс умирает сам по себе, он должен напечатать сообщение о стандартной ошибке (вот для чего он предназначен, и почему так важно, чтобы ошибки выводились со стандартной ошибкой, а не со стандартным выводом).
С этим сценарием у вас есть стандартный вывод output.txt
и стандартная ошибка собирается error.log
; скрипт не использует стандартный ввод (данные поступают из file.txt
). Таким образом, вы можете запустить это с nohup
или просто в фоновом режиме с &
безо всяких сомнений.
Вы можете предпочесть сделать имя file.txt
в параметры командной строки; Вы можете сделать вывод и файлы журнала настраиваемыми. Вы можете предпочесть другой формат для вывода даты. Все это настраивается. Но ключевой момент заключается в том, чтобы поместить его в сценарий оболочки, чтобы вы могли обрабатывать такие вещи прямо и систематически.
использование screen
, pv
а также tee
чтобы зафиксировать все ошибки, иметь индикатор выполнения и разрешить перезапуск с последней успешной команды, а не с нуля при ошибке.
Ты можешь использовать screen
( мультиплексор), а не в качестве фона вашего процесса. Таким образом, вы всегда можете просмотреть его статус и не пропустить сообщения об ошибках. Просто введите screen
запустите команду без &
и ударил CTRL-a,d
, Вы можете выйти из системы. Чтобы позже просмотреть вывод, войдите (даже удаленно) и введите screen -r
,
Furhtermore, если вы замените начальный cat
с pv
( просмотрщик каналов), у вас будет индикатор выполнения, показывающий, сколько уже обработано:
pv -cN file.txt
и вы увидите что-то вроде
611MB 0:00:11 [58.3MB/s] [=> ] 15% ETA 0:00:59
всякий раз, когда вы присоединяете screen
процесс.
В качестве альтернативы / дополнения, вы можете вставить tee
после команды, чтобы скопировать свой вывод в файл, прежде чем он будет распространен на следующий.
uniq -c | tee afteruniq.tmpfile | sort -gr
Файл afteruniq.tmpfile
будет содержать результат uniq -c
, Итак, вы знаете, что сработало, а что не удалось. Кроме того, вы можете возобновить цепочку после последнего успешного шага из tee
д файл.
Вы должны перенаправить оба stderr
а также stdout
в ваш выходной файл.
Сделайте свою команду такой:
( awk 'NR%4 == 2{print $1}' file.txt| sort | uniq -c | sort -gr ) >> output.txt 2>&1 &
Сделать заметку о 2>&1
перенаправить stderr
куда бы то ни было stdout
собирается