什么“bash:这个shell中没有工作控制”是什么意思?

时间:2012-08-06 00:41:23

标签: linux bash

我认为这与创建新子流程的父流程有关,并且没有tty。谁能解释引擎盖下的细节?即bash,流程创建等相关工作模型?

这可能是一个非常广泛的主题,所以非常感谢指向帖子的指针。我用谷歌搜索了一段时间,所有结果都是关于非常具体的情况,没有一个是关于场景背后的故事。为了提供更多上下文,下面是shell脚本导致'bash:此shell中没有作业控制'。

#! /bin/bash

while [ 1 ]; do
    st=$(netstat -an |grep 7070 |grep LISTEN -o | uniq)
    if [ -z $st ]; then
        echo "need to start proxy @$(date)"
        bash -i -c "ssh -D 7070 -N user@my-ssh.example.com > /dev/null"
    else
        echo "proxy OK @$(date)"
    fi
    sleep 3
done

这一行:

bash -i -c "ssh -D 7070 -N user@my-ssh.example.com > /dev/null"

是“bash:此shell中没有作业控制”的来源。

4 个答案:

答案 0 :(得分:28)

作业控制是shell和tty驱动程序中的一组功能,允许用户从单个交互式shell管理多个作业。

作业是单个命令或管道。如果你运行ls,那就是一份工作。如果你运行ls|more,那仍然只是一份工作。如果您运行的命令启动了自己的子进程,那么它们也将属于同一个作业,除非它们被故意分离。

如果没有作业控制,您可以通过向命令行添加&来将作业放在后台。这就是你拥有的所有控制权。

通过作业控制,您还可以:

  1. 使用 Ctrl Z 暂停正在运行的前台作业
  2. 使用fg
  3. 在前台恢复已暂停的作业
  4. 使用bg
  5. 在后台恢复暂停作业
  6. 使用fg
  7. 将正在运行的后台作业带到前台

    shell通过运行jobs命令维护一个可以看到的作业列表。为每个工作编号分配一个工作编号(不同于组成工作的工艺的PID)。您可以使用前缀为%的作业号作为fgbg的参数来选择前台或后台作业。 shell的内置kill命令也可以接受%jobnumber表示法。这很方便,因为作业号从1开始分配,所以它们比PID短。

    对于最近的前提工作,还有一些快捷方式%+和先前正在进行的工作的%-,因此您可以使用 Ctrl 在两个作业之间快速切换来回切换 Z 后跟fg %-(暂停当前的,恢复另一个),而不必记住数字。或者您可以使用命令本身的开头。如果您已暂停ffmpeg命令,则恢复它就像fg %ff一样简单(假设没有其他活动作业以“ff”开头)。作为最后一个快捷方式,您无需键入fg。只需输入%-作为命令即可显示上一个作业。

    “但我们为什么需要这个呢?”我能听到你问。 “如果我想运行另一个命令,我可以启动另一个shell。”没错,有多种多任务处理方式。在正常的一天,我有登录shell在tty1到tty10上运行(是的,有超过6个,你只需要激活它们),其中一个将运行一个屏幕会话,其中有4个屏幕,另一个可能正在运行ssh在它上面,在远程机器上运行另一个屏幕会话,加上我的X会话有3或4个xterms。我仍然使用工作控制。

    如果我在vilessaptitude或任何其他互动内容中,我需要运行其他一些快速命令来决定如何继续, Ctrl Z ,运行命令,fg自然而快速。 (在很多情况下,一个交互式程序有一个!键绑定来为你运行一个外部命令;我认为这不是很好,因为你没有从shell的历史,命令行编辑器和完成系统。)每当我看到有人启动辅助xterm / screen /无论运行一个命令,看了两秒钟然后退出时,我都觉得很难过。

    现在关于你的这个剧本。一般来说,它似乎没有完整的书面形式。有问题的一行:

    bash -i -c "ssh -D 7070 -N user@my-ssh.example.com > /dev/null"
    

    令人困惑。我无法弄清楚为什么ssh命令被传递到一个单独的shell而不是直接从主脚本执行,更不用说为什么有人添加了-i-i选项告诉shell以交互方式运行,这会激活作业控制(以及其他内容)。但它实际上并没有以交互方式使用。无论单独的shell和-i背后的目的是什么,关于工作控制的警告都是副作用。我猜这是一个克服ssh的一些不良特性的黑客攻击。这就是当你这样做时,你应该评论它。

答案 1 :(得分:23)

您可能需要启用作业控制:

#! /bin/bash   
set -m

答案 2 :(得分:20)

其中一个可能的选择是无法访问tty。

引擎盖下:

  1. bash检查会话是否是交互式的,如果不是 - 没有工作 控制。
  2. 如果设置了forced_interactive,则检查stderr是否为 附加到tty被跳过并再次进行bash检查,是否可以 打开/dev/tty进行读写访问。
  3. 然后检查是否使用了新的线路规则,如果没有,则也禁用工作控制。
  4. 如果(且仅当)我们将我们的流程组设置为我们的pid,从而成为流程组负责人,并且终端与我们的(新)流程组不在同一流程组中,则设置终端的流程组到我们的(新)流程小组。如果失败,请将我们的流程组恢复到原来的状态(这样我们仍然可以从终端读取)并关闭作业控制。
  5. 如果以上所有内容都失败了,您会看到该消息。
  6. 我部分引用了bash源代码的评论。

    [编辑]

    根据提问者的其他要求:

    http://tiswww.case.edu/php/chet/bash/bashtop.html在这里你可以找到bash本身。

    如果您可以阅读C代码,获取源代码tarball,您会在其中找到job.c - 那将更多地解释您“引擎盖下”的内容。 :)

答案 3 :(得分:2)

我在自己的嵌入式系统上遇到了问题,我通过使用“setsid”运行getty进程来摆脱“无作业控制”错误,根据其联机帮助页面启动了一个具有新会话ID的进程。

此致   的Heiko