簡體   English   中英

Linux CLI watch switch -e, --errexit 意外退出,“命令退出,非零狀態,按一個鍵退出”

[英]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 行。
可以選擇將stdoutstderr保存到文件中。

用作#!/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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM