2012-08-06 90 views
29

我认为它与父进程有关,创建新的子进程并没有tty。任何人都可以解释罩下的细节吗?即bash的相关工作模型,过程创建等?什么是“bash:在这个shell中没有任何控制”意思?

它可能是一个非常广泛的话题,所以指向帖子的链接也非常感谢。我Google搜索了一段时间,所有的结果都是关于非常具体的情况,没有一个是关于背后的故事。现场提供更多的上下文,以下是得到的“庆典:在这个壳无作业控制” 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 [email protected] > /dev/null" 
    else 
     echo "proxy OK @$(date)" 
    fi 
    sleep 3 
done 

这行:

bash -i -c "ssh -D 7070 -N [email protected] > /dev/null"

就是“击:这个壳无作业控制”从何而来。

+2

我无法从你的问题告诉你是否要在一般的外壳上作业控制信息,或解释为什么在某些情况下工作控制不可用。 – kojiro 2012-08-06 00:46:49

+0

他们两人:)它可能是一个非常广泛的话题,所以指向职位的人也非常感激。我谷歌搜索了一段时间,所有的结果都是关于非常具体的情况,没有一个是关于幕后的故事。 – luanjunyi 2012-08-06 03:39:32

+0

是否有你启动一个新shell来启动SSH的原因?从命令行运行你的脚本不会给我“无工作控制”,尽管它只是挂在SSH执行上,实际上它应该这样做。所以从技术上讲,“其他”不会被打到。你从哪里运行这个脚本? crontab的? – favoretti 2012-08-06 06:54:34

回答

16

其中一种可能的选择是不能访问tty。

引擎盖下:

  1. 庆典检查会话是否是互动的,如果没有 - 没有工作 控制。
  2. 如果设置了forced_interactive,则检查连接到tty的stderr是否为 会被跳过,并且bash会再次检查是否可以在 打开/dev/tty进行读写访问。
  3. 然后它检查是否使用了新的线条规则,如果没有,则作业控制也被禁用。
  4. 如果(且仅当)我们只将过程组设置为我们的PID,从而成为过程组领导,并且终端与我们的(新)过程组不在同一过程组中,则设置终端的过程组到我们的(新)流程组。如果失败,请将我们的过程组重新设置为原来的状态(以便我们仍可以从终端读取)并关闭作业控制。
  5. 如果以上全部失败,您会看到该消息。

我部分引用了bash源代码中的注释。

[编辑]

按照问题笔者的额外要求:

http://tiswww.case.edu/php/chet/bash/bashtop.html在这里,你可以找到自己的bash。

如果您可以阅读C代码,请获取源代码压缩包,在其中您会发现job.c - 这将为您解释更多“底层”的内容。 :)

19

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

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

如果没有作业控制,您可以通过将&添加到命令行中来将作业置于后台。这就是你所有的控制。

作业控制,您还可以:

  1. 挂起正在运行的前台作业与按Ctrlž
  2. 继续在前台挂起的作业与fg
  3. 继续暂停作业与bg
  4. 的背景与带来正在运行的后台作业前景0

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

也有快捷键%+为先前前景化工作的最近前景化工作,%-,这样你就可以来回切换迅速两份工作按Ctrl之间,ž其次fg %-(暂停当前一个,恢复另一个),而不必记住数字。或者你可以使用命令本身的开始。如果您已暂停ffmpeg命令,则恢复该命令与fg %ff一样简单(假定没有其他活动作业以“ff”开头)。作为最后一个捷径,您不必输入fg。只要输入%-作为一个命令前面的工作前景。

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

如果我在viless或​​或任何其他互动的东西中间,我需要运行其他几个快捷命令来决定如何进行,按Ctrlž,运行命令,和fg是自然而快速的。 (在很多情况下,一个交互式程序有一个!键绑定为你运行一个外部命令;我认为这并不好,因为你没有得到shell的历史,命令行编辑器和完成系统的好处。)当我看到有人启动辅助xterm/screen /无论运行哪一个命令,看它两秒钟,然后退出时,我感到很伤心。

现在关于你的脚本。总的来说,它似乎没有写得很好。有问题的线路:

bash -i -c "ssh -D 7070 -N [email protected] > /dev/null" 

令人困惑。我无法弄清楚为什么ssh命令被传递到一个单独的shell而不是直接从主脚本执行,更不用说为什么有人添加了-i-i选项告诉shell以交互方式运行,这会激活作业控制(等等)。但它并没有真正被交互使用。无论背后单独的壳和-i的目的是什么,关于工作控制的警告是一个副作用。我猜测这是一个破解ssh的一些不受欢迎的功能的黑客。这是当你这样做的时候,你应该评论它。

+0

谢谢@Alan。该脚本的目的是持续监视SSH隧道是否打开,如果没有,则创建一个。我的浏览器使用这个隧道的袜子代理。我绝不是一个有能力的bash编码器。整个脚本是通过尝试错误构建的。我使用了'bash -i',希望启动ssh命令是类似fork的,而不是exec,就像原来的监视过程停止了一样。请纠正我一个更好的解决方案。目前这个脚本除了生成'无作业控制'消息外还可以正常工作。 – luanjunyi 2012-08-07 05:04:53

+1

当你在一行上只有ssh -D 7070 -N [email protected]>/dev/null'时,它做了什么不同的操作(除了不打印“no job control warning”) ,没有'bash -i -c'? – 2012-08-07 07:19:03

2

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

问候, 海科

+3

我不认为这真的回答了这个问题,至多这应该是一个评论。 – meskobalazs 2015-02-10 13:22:41

5

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

#! /bin/bash 
set -m