标准输入冻结在后台时,在前台当它解冻 [英] Freeze stdin when in the background, unfreeze it when in the foreground

查看:270
本文介绍了标准输入冻结在后台时,在前台当它解冻的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在后台运行一个sript:

I am trying to run a sript in the background:

nohup script.py > out 2> err < /dev/null &

该脚本(的Python 3.4 )确实在一些点:

answer = input('? ')

(它有在其中一个线程运行的菜单)

(it has a menu running in one of the threads)

和命令nohup调用与崩溃:

And the nohup call is crashing with:

EOFError: EOF when reading a line

由于标准输入的/ dev / null的重定向我的想象。如果我运行它没有标准输入重定向:

Because of the /dev/null redirection of stdin I imagine. If I run it without stdin redirection:

nohup script.py > out 2> err &

这与崩溃:

OSError: [Errno 9] Bad file descriptor

如果我运行它:

script.py > out 2> err

它的工作原理,但我的块终端(这是在前台)

It works, but blocks my terminal (it is in the foreground)

如果我运行它:

script.py > out 2> err &

它在后台运行好的,但它得到尽快停止为输入达到电话。

我想的是:


  • 能够重定向标准输出标准错误到文件系统

  • 能够把这个脚本在后台

  • 可以,如果到前台正常运行,并与之交互菜单(所以标准输入必须以某种方式启用)。 标准输出标准错误仍然会被重定向到文件系统,但标准输入通常会做人。

  • 脚本必须在后台运行,并在前台精(当然,菜单是不是在后台运行,因为标准输入是冻结)

  • be able to redirect stdout and stderr to the filesystem
  • be able to put the script in the background
  • be able to move if to the foreground and interact with the menu normally (so stdin must be enabled somehow). stdout and stderr would still be redirected to the filesystem, but stdin would behave normally.
  • the script must run fine in the background and in the foreground (of course, the menu is not working in the background, because stdin is "frozen")

基本上,我想的是,当它在后台运行,标准输入是一种冻结,每当涉及到前台它的工作再正常

Basically, what I would like is that when it is in the background, stdin is kind of "frozen", and whenever it comes to the foreground it works again normally.

这可能吗?该解决方案并不需要涉及到的nohup

Is this possible? The solution does not need to involve nohup

推荐答案

您想要什么(以及如何输入作品和失败的 EOF 的python)与交互菜单意味着你不能安全地传递一个文件作为标准输入调用程序时。这意味着你唯一的选择就是调用这个像这样:

What you want (and how input works and fails on EOF under python) with an interactive menu means that you cannot safely pass a file as stdin when invoking your program. This means your only option is to invoke this like so:

$ script.py > out 2> err &

作为示范,这是我的脚本:

As a demonstration, this is my script:

from time import sleep
import sys

c = 0
while True:
    sleep(0.001)
    c += 1
    if c % 1000 == 0:
        print(c, flush=True)
    if c % 2000 == 0:
        print(c, file=sys.stderr, flush=True)
    if c % 10000 == 0:
        answer = input('? ')
        print('The answer is %s' % answer, flush=True)

基本上,每一秒都将会写入标准输出,每两秒钟将会写入标准错误,最后,每十秒它将等待输入。如果我要运行这个等待有点超过秒(允许磁盘刷新),和链了一起,就像这样:

Essentially, every second it will write to stdout, every two seconds it will write to stderr, and lastly, every ten seconds it will wait for input. If I were to run this and wait a bit over a seconds (to allow disk flush), and chain this together, like so:

$ python script.py > out 2> err & sleep 2.5; cat out err
[1] 32123
1000
2000
2000
$ 

至少等待10秒,并试图猫了ERR 又说:

$ cat out err
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
? 2000
4000
6000
8000
10000

[1]+  Stopped                 python script.py > out 2> err
$ 

请注意,通过生成的提示输入也写到标准输出,并且该方案继续有效地在那里期待标准输入给它的数据。您只需通过来使这一进程回到前台,并开始喂养它需要的数据,然后用 ^ Z (<大骨节病>控制 <大骨节病>以Z ),并把它与%放后台重新运行; 。例如:

Note that the prompt generated by input is also written to stdout, and the program effectively continued running up to where it is expecting stdin to give it data. You simply have to bring the process back into foreground by %, and start feeding it the required data, then suspend with ^Z (CtrlZ) and keep it running again in the background with %&. Example:

$ %
python script.py > out 2> err
Test input
^Z
[1]+  Stopped                 python script.py > out 2> err
$ %&
[1]+ python script.py > out 2> err &
$

现在猫了再次,等待另一个在十秒钟后:

Now cat out again, after waiting another ten seconds:

$ cat out
1000
...
10000
? The answer is Test input
11000
...
20000
? 
[1]+  Stopped                 python script.py > out 2> err
$

这实质上是在怎样的标准流程中的前景和背景一般功能的基本速成班,事情只是单纯的工作,如果code正确处理标准IO如预期。

This is essentially a basic crash course in how standard processes typically functions in both foreground and background, and things just simply work as intended if the code handles the standard IO correctly.

最后,你真的不能两者兼得。如果应用程序需要标准输入,并没有提供,那么明确的选择是失败的。如果一个人但前提却得到了应用发送到后台,并不停地奔跑,这将是停止,因为它希望进一步的输入。如果停止行为是不必要的,应用程序有过错,没有什么可以做,但更改应用程序产生的结果不会在当执行中遇到 EOF 错误的/ dev / null的标准输入。如果你想保持标准输入为是,与应用程序能够以某种方式继续运行,当它在后台,你不能使用输入的功能,因为它会阻止时,标准输入为空(产生过程中被停止)。

Lastly, you can't really have it both ways. If the application expects stdin and none is provided, then the clear option is failure. If one is provided however but application got sent to background and kept running, it will be Stopped as it expects further input. If this stopped behaviour is unwanted, the application is at fault, there is nothing can be done but to change the application to not result in an error when EOF is encountered when executed with /dev/null as its stdin. If you want to keep stdin as is, with the application being able to somehow keep running when it is in the background you cannot use the input function as it will block when stdin is empty (resulting in process being stopped).

现在,您已经通过下面的评论澄清说,你的交互提示在一个线程中运行,并且由于输入直接从标准输入,你似乎不愿意修改程序(你问一般情况下),但需要一个工具来为你做这个,简单的解决方案是一个的 TMUX 或的 屏幕 会议,因为他们全面落实伪TTY是独立于任何启动控制台(这样你就可以断开连接,会议发送到背景中,或启动其他虚拟会话,请参阅手册页),将提供标准输入输出,该计划预计。

Now that you have clarified via the comment below that your "interactive prompt" is running in a thread, and since usage of input directly reads from stdin and you seem unwilling to modify your program (you asking for general case) but expects a utility to do this for you, the simple solution is to execute this within a tmux or screen session as they fully implement a pseudo tty that is independent from whichever console that started (so you can disconnect and send the session to the background, or start other virtual sessions, see manual pages) which will provide stdio that the program expects.

最后,如果你真的想你的应用程序本身支持这一点,你不能简单地使用输入的是,但你应该检查是否输入可以安全地被调用(即可能利用 选择 ),或者通过检查进程是否是当前在前台或后台(你可以开始从为<工作的一个例子href=\"http://stackoverflow.com/questions/24861351/how-to-detect-if-python-script-is-being-run-as-a-background-process/24862213#24862213\">How检测是否python脚本正在运行作为后台进程,虽然你可能想使用检查 sys.stdin ,也许吧。),以确定是否输入可以安全地调用,或使用UNIX(但是,如果用户的输入是它仍然会挂起为输入等待挂起任务)插座沟通。

Finally, if you actually want your application to support this natively, you cannot simply use input as is, but you should check whether input can safely be called (i.e. perhaps making use of select), or by checking whether the process is currently in the foreground or background (An example you could start working from is How to detect if python script is being run as a background process, although you might want to check using sys.stdin, maybe.) to determine if input can be safely called (however if user suspends the task as input comes it would still hang as input waits), or use unix sockets for communication.

这篇关于标准输入冻结在后台时,在前台当它解冻的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆