Я ищу способ ограничить объем данных, хранящихся в переменной Bash, которая инициализируется из выходных данных подпроцесса.
Проблема этого потенциального решения заключается в том, что оно сохраняет весь вывод перед его усечением.
#!/bin/bash
COMMAND_TO_RUN="du /"
OUT_DATA=$($COMMAND_TO_RUN)
OUT_RESULT=$?
if [[ $OUT_RESULT -ne 0 ]]; then
echo "${OUT_DATA:0:10000}" | head mail -s "Command failed" [email protected]
fi
Альтернатива OUT_DATA=$($COMMAND_TO_RUN | head -c 10000)
отменяет команду, когда считываются первые 10 КБ вывода, и мне нужно, чтобы команда выполнилась до конца, чтобы зафиксировать ее состояние выхода.
Я могу сделать это довольно легко в python
, но надеюсь на bash
единственное решение. И также не прибегая к записи на диск.
решение1
С функцией. Для удобства чтения в примере ниже команда и т.п. жестко закодированы.
truncated_du() {
du / | { head -c 10000; cat >/dev/null; }
return "${PIPESTATUS[0]}"
}
out_data="$(truncated_du)"
out_result="$?"
head
передает не более желаемого объема данных в stdout функции. Если данных больше, cat
отбрасывает их без прерывания du
. Статус выхода du
извлекается из PIPESTATUS
массива и возвращается функцией.
Примечание: мои переменные используют lower case
; см.этот ответ.
Без функции то же самое решение выглядит так:
out_data="$(
du / | { head -c 10000; cat >/dev/null; }
exit "${PIPESTATUS[0]}"
)"
out_result="$?"
По моему мнению, так текст становится менее читабельным.
решение2
Это ограничивает объем захвата, но я предполагаю, что он завершается со read
статусом выхода s (я не знаю, останавливается ли он, но останавливает команду, как head
это было бы, потому что статус выхода не соблюдается: `
IFS= read -r -d '' -n $chars_to_capture foo < <($command)
Похоже, что команда выполняется до конца, но вы не получаете статус завершения команды, а получаете read
статус завершения s, что бесполезно.
Пример
$ IFS= read -r -d '' -n 19 foo < <(seq 50; touch somefile; exit 42); echo "exit=$?"; ls -l somefile
exit=0
-rw-r--r-- 1 glennjackman staff 0 Jul 22 22:04 somefile
Я предполагаю, что тот факт, что файл затронут, означает, что команда не прерывается после захвата запрошенного количества символов.
Возможно, вы могли бы записать статус выхода в файл в подоболочке:
IFS= read -r -d '' -n 10000 out_data < <( $command_to_run; echo $? > statusfile )
if [[ -f statusfile ]] && [[ "$(<statusfile)" != "0" ]]; then
printf "%s\n" "$out_data" | head mail -s "Command failed" [email protected]
rm statusfile
fi