标准输入冻结在后台时,在前台当它解冻 [英] Freeze stdin when in the background, unfreeze it when in the foreground
问题描述
我想在后台运行一个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
andstderr
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
andstderr
would still be redirected to the filesystem, butstdin
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
$
请注意,通过生成的提示输入
也写到标准输出,并且该方案继续有效地在那里期待标准输入运行速度高达code>给它的数据。您只需通过
%
来使这一进程回到前台,并开始喂养它需要的数据,然后用 ^ Z $ C $暂停C>(<大骨节病>控制骨节病> <大骨节病>以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屋!