【问题标题】:Bash, timeout 'ls | wc -l'重击,超时'ls |厕所-l'
【发布时间】:2016-09-03 19:59:39
【问题描述】:

我已经在这个网站和谷歌上搜索了如何让 bash 命令超时,如果它需要很长时间才能运行,并且尝试了多种不同的方法,但似乎都无法正常工作。

具体来说,我需要超时 'ls | wc -l' 如果运行时间超过 10 秒;但是,我将运行 'ls | wc -l' 在多个目录上,如果只需要一秒钟即可完成,不想为每个目录等待 10 秒。

我已经尝试过,这似乎只是一种工作,但是当 'ls | wc -l' 在 10 秒睡眠前结束。

ls /file/path/to/count/ | wc -l &
pidsave=$!
sleep 1
if [ -e /proc/$pidsave ]; then
kill $pidsave; echo $?
echo 'ls command was timed out'
else
echo 'ls command completed'
fi

【问题讨论】:

    标签: bash timeout


    【解决方案1】:

    您可以使用timeout 命令:

    if timeout 10 ls /file/path/to/count/ | wc -l; then
        echo "Successful!!"
    else
        echo "Timed Out!!"
    fi
    

    检查man timeout

    【讨论】:

    • 我已经尝试过 timeout 命令,但它从来没有对我有用。当我尝试您提供的选项和 'ls | wc -l' 时间到了,它仍然显示“成功”消息以及计数为 0。这就像“else”自超时以来从未使用过,“ls | wc -l' 命令是同一个 'if' 语句的一部分。还有其他想法吗?
    • @mtucker136 不过对我来说工作得很好。如果您从wc 获得任何输出,则管道会在超时发生之前完成。检查较低的超时时间,如0.001
    【解决方案2】:

    之前发布的答案也对我不起作用。 问题在于if 测试的是wc -l 的结果,而不是实际的timeout

    为避免这种情况,您可以将命令包装在一个函数中,将命令放入一个可执行文件中,或者取消链接命令并单独执行它们,具体取决于您实际需要对您的输出中的输出做什么上下文。

    选项 1 - 功能

    函数必须导出到子shell,然后在子shell下执行。

    #!/bin/bash
    function my_ls {
        ls | wc -l
    }
    
    export -f my_ls
    timeout 10 bash -c my_ls
    if [ $? -eq 0 ]; then
        echo "cmd finished in time"
    else
        echo "cmd did NOT finish in time"
    fi
    

    选项 2 - 文件

    ls | wc -l 放入某个文件(例如/tmp/ls.sh)并使其可执行(chmod +x /tmp/ls.sh)。将该文件用作timeout 命令的参数:

    #!/bin/bash
    MY_FILE="/tmp/ls.sh"
    echo "ls | wc -l" > $MY_FILE
    chmod +x $MY_FILE
    
    timeout 10 $MY_FILE
    if [ $? -eq 0 ]; then
        echo "cmd finished in time"
    else
        echo "cmd did NOT finish in time"
    fi
    

    选项 3 - 未链接

    假设ls 是本示例中可能需要很长时间才能完成的命令,请先运行该命令。可能的输出存储在一个变量中(假设命令没有超时),您可以稍后使用它:

    #!/bin/bash
    LIST="$(timeout 10 ls)"
    if [ $? -eq 0 ]; then
        echo "cmd finished in time"
        echo $(wc -l <<< $LIST)
    else
        echo "cmd did NOT finish in time"
    fi
    

    【讨论】:

    • 非常感谢,选项 3 成功了!我将我的代码添加为答案,因为我不知道如何添加为评论。
    【解决方案3】:

    在 Jiri 的帮助下,选项 3 成功了。这是我正在使用的确切代码,以防有人感兴趣。我将它包装在一个 for 语句中,并提供了一个浅蓝色的 Count 标题,超时!!!以红色显示,实际计数以绿色显示。

    echo -e "\e[1;4;36mCount\e[0m" >> $LOGPATH
    for c in $DIR1 $DIR2 $DIR3 $DIR4; do
    
    LIST=$(timeout 2 ls $c &>/dev/null; echo $?)
    if [ $LIST != 0 ]; then
        echo -e $c "\e[1;31mTIMED OUT!!! \e[0m" >> $LOGPATH
    else
      echo -e $c "\e[1;32m$(ls $c |wc -l) \e[0m" >> $LOGPATH
    fi
    
    done
    

    【讨论】:

      猜你喜欢
      • 2020-10-11
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多