[英]Linux CLI watch switch -e, --errexit unexpected exit with “command exit with a non-zero status, press a key to exit”
Linux CLI watch
命令有一個開關-e
, --errexit
有一個描述:
在命令錯誤時凍結更新,並在按鍵后退出。
如果該開關返回非零退出代碼,則該開關應使手表停止執行命令。
問題是,如果命令的 output 不適合 CLI window,則watch
將終止。 當 CLI window 在 Ubuntu 18.04 上全屏時,有時會出現問題,並且總是在調整 window 大小或小於全屏時出現問題。
具有命令的腳本示例:
任務.sh
#!/bin/sh
for i in $(seq 1 200)
do
printf "Task #${i}\n";
done
exit 0;
並監視命令:
watch -e -n 1 ./task.sh;
觀看意外錯誤:
命令以非零狀態退出,按一個鍵退出
如何解決這個問題? 我無法將標准 output 重定向到/dev/null
因為至少需要打印使用watch
執行的命令的部分 output 並且如果執行腳本的任何命令返回非零退出代碼,則手表應該終止,所以我猜我m 被迫使用-e
, --errexit
開關。
如果對特定的watch
行為沒有好的解決方案, watch
有什么好的替代品嗎?
編輯
看起來watch
問題與打印超過可見終端 output 的多個命令而不是打印字符串的總數有關。 此示例使用單個printf
並且在調整終端屏幕大小時沒有任何問題,即使它打印的內容超過了終端的可見部分:
#!/bin/sh
output="";
for i in $(seq 1 200)
do
output="${output}$(printf "Task #${i}")\n";
done
printf "$output";
exit 0;
但是這個 hack 可以使用相對較小的腳本,我無法想象使用 watch 並為 task.sh srcipt 中的每個命令做這個解決方法
另一種解決方法:
#!/usr/bin/env bash
temp="$(mktemp /tmp/watch.XXXXXXX)"
exec 3>&1; exec > $temp
date # for demo purpose
for i in $(seq 1 200)
do
printf "Task #${i}\n";
done
exec 1>&3
cat $temp; rm $temp
所以你不需要對原來的 bash 腳本做太多改動。
我想不出使用變量的方法,如果 tmp 文件真的是個問題,試試這個:
#!/usr/bin/env bash
{
date # for demo purpose
for i in $(seq 1 200)
do
printf "Task #${i}\n";
done
} | head -n $LINES
帶有-e
開關的watch
任務包裝器(出錯時退出)。
調整終端 window 的大小時沒有任何問題,甚至只有 1 行。
可以選擇將stdout
和stderr
保存到文件中。
用作#!/bin/bash
或#!/bin/sh
任務包裝器.sh
#!/bin/sh
# path to file where to put stdout and stderr on error
error_log="$1";
output="$(
# exit sub shell with non zero code on
# any line in sub shell having non zero exit code
set -e;
{
# ========== Commands Block =============
# uncomment below to simulate an error
# ls /this/is/non/existing/path;
# an example of lot of print exceeding
# count of displayed terminal lines
for i in $(seq 1 200)
do
printf "Task #${i}\n";
done
# uncomment below to simulate an error
# ls /this/is/non/existing/path;
# ========== Commands Block =============
} 2>&1;
)";
# get sub shell exit code
# print output (limit to terminal capacity)
# save error if any
# exit with error code if any
# or exit 0;
ec="$?"; if [ $ec -eq 0 ]; then
# zero exit code
# prevent echo if there are only two
# lines of terminal available because
# they may be already consumed by watch
# and its status if watch run without
# --no-title switch (default)
if [ $LINES -gt 2 ]; then
echo "$output" | tail -n "$(($LINES - 2))";
fi;
exit 0;
else
# non zero exit code
# watch on error
# consumes additional one line
# therefore don't echo if lines
# available are less than 4
if [ "$LINES" -gt 3 ]; then
echo "$output" | tail -n "$(($LINES - 3))";
fi;
# watch erases terminal
# output after press of any key
# and its teminal print has no scroll
# so save whole stdout and stderr to file
# if path to it was provided
if [ -n "$error_log" ]; then
echo "$output" > "$error_log";
fi;
# exit with sub shell exit code
exit "$ec";
fi;
用法:
watch -e ./task-wrapper.sh
使用創建為錯誤日志的文件路徑
watch -e ./task-wrapper.sh ./task-error.log
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.