python - bash 脚本中的 coreutils 超时对于应用程序不透明

标签 python linux bash terminal timeout

我在 bash 脚本中通过/usr/bin/timeout 执行应用程序时遇到问题。 在本例中,这是一个简单的 python Fabric 脚本(fabric 版本 1.14) 要安装此版本的结构库,请运行: pip install "fabric<2" 新 Fabric 2.x 没有再现。

Shell 脚本导致问题:

[root@testhost:~ ] $ cat testNOK.sh
#!/bin/bash
timeout 10 ./test.py
echo "RETCODE=$?"
[root@testhost:~ ] $ ./testNOK.sh
[localhost] run: echo Hello!
RETCODE=124
[root@testhost:~ ] $

类似的脚本(没有超时)工作正常

[root@testhost:~ ] $ cat testOK.sh
#!/bin/bash
./test.py
echo "RETCODE=$?"
[root@testhost:~ ] $ ./testOK.sh
[localhost] run: echo Hello!
[localhost] out: Hello!
[localhost] out:

RETCODE=0
[root@testhost:~ ] $

从 bash 命令行手动执行,超时工作正常:

[root@testhost:~ ] $ timeout 10 ./test.py && echo "RETCODE=$?"
[localhost] run: echo Hello!
[localhost] out: Hello!
[localhost] out:

RETCODE=0
[root@testhost:~ ] $

Python2.7 test.py脚本

[root@testhost:~ ] $ cat test.py
#!/usr/bin/python
from fabric.api import run, settings

with settings(host_string='localhost', user='root', password='XXXXX'):
    run('echo Hello!')
[root@testhost:~ ] $

我在不同的 Linux 发行版上观察到相同的行为。

现在的问题是,为什么 bash 脚本中通过超时执行的应用程序的行为方式不同,以及解决此问题的最佳解决方案是什么?

最佳答案

您需要使用 --foreground 选项调用 timeout:

timeout --foreground ./test.py

仅当 timeout 命令不是从交互式 shell 执行(即从脚本文件执行)时才需要。

引用超时信息页面:

‘--foreground’
     Don’t create a separate background program group, so that the
     managed COMMAND can use the foreground TTY normally.  This is
     needed to support timing out commands not started directly from an
     interactive shell, in two situations.
       1. COMMAND is interactive and needs to read from the terminal for
          example
       2. the user wants to support sending signals directly to COMMAND
          from the terminal (like Ctrl-C for example)

在这种情况下实际发生的是,fabric(或某些调用)正在调用 tcsetattr 来关闭终端回显。我不知道为什么,但我认为这与用于(不)收集用户密码的过程有关。 (我只是在 strace 中看到它;我没有尝试找到该调用。)尝试从后台进程更改 tty 配置将导致进程阻塞,直到它重新获得对 tty 的控制,这就是正在发生的情况。

不使用timeout时不会发生这种情况,因为bash不会创建后台程序组。我认为 Fabric 2 避免了对 tcsetattr 的调用。

您或许还可以通过避免基于密码的 SSH 身份验证来避免该问题,但我没有尝试这样做。

您还可以通过将 stdin 重定向到 /dev/null(在 timeout 命令中或在 shell 脚本的调用中)来避免此问题。如果您不需要将 stdin 转发到远程命令(而且您可能不需要),这也可能很有用。

关于python - bash 脚本中的 coreutils 超时对于应用程序不透明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52008104/

相关文章:

python - 如何在 Python/Gdk 中编辑 pixbuf 的像素

linux - 我无法在 Ubuntu 上安装 xde expo

windows - 帮助处理 Cygwin bash 文件

python - 合并两行数据并连接值(如果唯一)-Pandas

python - DJango - NoReverseMatch 错误

python - 在python中的mysql表中插入时间戳

linux - Makefile 没有按预期执行命令

c++ - 如何在linux下用c/c++构建igmp查询生成器

bash - Raspberry Pi 红外接收器软件

c - 如何在 eclipse 和 bash 上运行接受参数的代码?