Linux “bash:no job control in this shell”是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11821378/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:01:13  来源:igfitidea点击:

what does "bash:no job control in this shell” mean?

linuxbash

提问by luanjunyi

I think it's related to the parent process creating new subprocess and does not have tty. Can anyone explain the detail under the hood? i.e. the related working model of bash, process creation, etc?

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

It may be a very broad topic so pointers to posts are also very appreciated. I've Googled for a while, all the results are about very specific case and none is about the story behind the scene. To provide more context, below is the shell script resulting the 'bash: no job control in this shell'.

这可能是一个非常广泛的主题,因此也非常感谢指向帖子的指针。我用谷歌搜索了一段时间,所有的结果都是关于非常具体的案例,没有一个是关于幕后故事的。为了提供更多上下文,下面是导致“bash: no job control in this shell”的 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

This line:

这一行:

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

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

is where "bash:no job control in this shell” come from.

是“bash:no job control in this shell”的来源。

回答by favoretti

One of the possible options would be not having access to the tty.

一种可能的选择是无法访问 tty。

Under the hood:

引擎盖下:

  1. bash checks whether the session is interactive, if not - no job control.
  2. if forced_interactive is set, then check that stderr is attached to a tty is skipped and bash checks again, whether in can open /dev/ttyfor read-write access.
  3. then it checks whether new line discipline is used, if not, then job control is disabled too.
  4. If (and only if) we just set our process group to our pid, thereby becoming a process group leader, and the terminal is not in the same process group as our (new) process group, then set the terminal's process group to our (new) process group. If that fails, set our process group back to what it was originally (so we can still read from the terminal) and turn off job control.
  5. if all of the above has failed, you see the message.
  1. bash 检查会话是否是交互式的,如果不是 - 没有作业控制。
  2. 如果设置了forced_interactive,则检查stderr 是否附加到tty 被跳过并再次检查bash,是否可以打开/dev/tty进行读写访问。
  3. 然后检查是否使用了新的生产线纪律,如果没有,则作业控制也被禁用。
  4. 如果(且仅当)我们只是将我们的进程组设置为我们的 pid,从而成为进程组组长,并且终端与我们的(新)进程组不在同一个进程组中,那么将终端的进程组设置为我们的(新)进程组。如果失败,将我们的进程组设置回原来的状态(这样我们仍然可以从终端读取)并关闭作业控制。
  5. 如果以上所有操作均失败,您会看到该消息。

I partially quoted the comments from bash source code.

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

[edit]

[编辑]

As per additional request of the question author:

根据问题作者的额外要求:

http://tiswww.case.edu/php/chet/bash/bashtop.htmlHere you can find bash itself.

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

If you can read the C code, get the source tarball, inside it you will find job.c- that one will explain you more "under the hood" stuff. :)

如果您可以阅读 C 代码,获取源 tarball,您会在job.c其中找到-它将向您解释更多“幕后”的东西。:)

回答by Alan Curry

Job controlis a collection of features in the shell and the tty driver which allow the user to manage multiple jobs from a single interactive shell.

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

A job is a single command or a pipeline. If you run ls, that's a job. If you run ls|more, that's still just one job. If the command you run starts subprocesses of its own, then they will also belong to the same job unless they are intentionally detached.

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

Without job control, you have the ability to put a job in the background by adding &to the command line. And that's about all the control you have.

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

With job control, you can additionally:

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

  1. Suspend a running foreground job with CtrlZ
  2. Resume a suspended job in the foreground with fg
  3. Resume a suspend job in the background with bg
  4. Bring a running background job into the foreground with fg
  1. 暂停正在运行的前台作业 CtrlZ
  2. 在前台恢复暂停的工作 fg
  3. 使用以下命令在后台恢复暂停作业 bg
  4. 将正在运行的后台作业带入前台 fg

The shell maintains a list of jobs whcih you can see by running the jobscommand. Each one is assigned a job number (distinct from the PIDs of the process(es) that make up the job). You can use the job number, prefixed with %, as an argument to fgor bgto select a job to foreground or background. The %jobnumber notation is also acceptable to the shell's builtin killcommand. This can be convenient because the job numbers are assigned starting from 1, so they're shorter than PIDs.

shell 维护着一个作业列表,您可以通过运行jobs命令查看这些作业。每个人都被分配了一个作业号(与组成该作业的进程的 PID 不同)。您可以使用前缀为%,的作业编号作为参数fgbg选择将作业置于前台或后台。shell 的内置kill命令也可以接受 %jobnumber 符号。这很方便,因为作业编号从 1 开始分配,因此它们比 PID 短。

There are also shortcuts %+for the most recently foregrounded job and %-for the previously foregrounded job, so you can switch back and forth rapidly between two jobs with CtrlZfollowed by fg %-(suspend the current one, resume the other one) without having to remember the numbers. Or you can use the beginning of the command itself. If you have suspended an ffmpegcommand, resuming it is as easy as fg %ff(assuming no other active jobs start with "ff"). And as one last shortcut, you don't have to type the fg. Just entering %-as a command foregrounds the previous job.

也有快捷键%+为最近前景化作业,并%-为以前前景化的工作,这样你就可以在两个工作之间有来回切换迅速CtrlZ,随后fg %-(暂停当前,恢复另外一个),而不必记住的数字。或者您可以使用命令本身的开头。如果您暂停了一个ffmpeg命令,恢复它就像fg %ff(假设没有其他活动作业以“ff”开头)一样简单。作为最后一个快捷方式,您不必输入fg. 只需%-作为命令输入即可将上一个作业置于前台。

"But why do we need this?" I can hear you asking. "I can just start another shell if I want to run another command." True, there are many ways of multitasking. On a normal day I have login shells running on tty1 through tty10 (yes there are more than 6, you just have to activate them), one of which will be running a screen session with 4 screens in it, another might have an ssh running on it in which there is another screen session running on the remote machine, plus my X session with 3 or 4 xterms. And I still use job control.

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

If I'm in the middle of vior lessor aptitudeor any other interactive thing, and I need to run a couple of other quick commands to decide how to proceed, CtrlZ, run the commands, and fgis natural and quick. (In lots of cases an interactive program has a !keybinding to run an external command for you; I don't think that's as good because you don't get the benefit of your shell's history, command line editor, and completion system.) I find it sad whenever I see someone launch a secondary xterm/screen/whatever to run one command, look at it for two seconds, and then exit.

如果我正处于vilessaptitude或任何其他交互式事物的中间,并且我需要运行其他几个快速命令来决定如何继续CtrlZ,运行这些命令,并且fg自然而快速。(在很多情况下,交互式程序具有!为您运行外部命令的键绑定;我认为这不是很好,因为您没有从 shell 的历史记录、命令行编辑器和完成系统中受益。)我每当我看到有人启动辅助 xterm/screen/whatever 来运行一个命令时,我都会感到难过,看着它两秒钟,然后退出。

Now about this script of yours. In general it does not appear to be competently written. The line in question:

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

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

is confusing. I can't figure out why the ssh command is being passed down to a separate shell instead of just being executed straight from the main script, let alone why someone added -ito it. The -ioption tells the shell to run interactively, which activates job control (among other things). But it isn't actually being used interactively. Whatever the purpose was behind the separate shell and the -i, the warning about job control was a side effect. I'm guessing it was a hack to get around some undesirable feature of ssh. That's the kind of thing that when you do it, you should comment it.

令人困惑。我不明白为什么 ssh 命令被传递到一个单独的 shell 而不是直接从主脚本执行,更不用说为什么有人添加-i到它了。该-i选项告诉 shell 以交互方式运行,从而激活作业控制(除其他外)。但实际上并没有以交互方式使用它。无论单独的 shell 和 背后的目的是什么-i,关于作业控制的警告都是副作用。我猜想绕过 ssh 的一些不受欢迎的功能是一种黑客攻击。这就是当你做的时候,你应该评论它的那种事情。

回答by Heiko Gerstung

I ran into a problem on my own embedded system and I got rid of the "no job control" error by running the getty process with "setsid", which according to its manpage starts a process with a new session id.

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

Regards, Heiko

问候, 海科

回答by Marian

You may need to enable job control:

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

#! /bin/bash   
set -m