ff5*_*524 10 bash shell background-process pbs torque
从打印在后台的函数打印输出后,如何自动返回到bash提示符?
例如,当我在bash shell中运行以下脚本时:
fn(){ sleep 10 echo "Done" exit } fn &
运行脚本后,它会立即返回我的提示.10秒后,它会打印"完成",然后在新行上显示一个闪烁的光标:
$ Done ?
脚本不再运行了,但是在我按下之前我没有收到提示Return.
打印"完成"后有没有办法强制返回bash提示符?
一个相关的问题是:是否有办法让后台任务通知终端打印新提示?但是,这个问题询问了一个背景计划.提供有答案适用于程序发送到后台,但似乎并没有为工作函数发送到后台(在我提供的例子).
澄清:我希望保存上面的整个代码片段(例如,as myscript.sh
),然后将其作为前台脚本运行(例如,as bash myscript.sh
).
编辑:以上当然只是一个MWE.这个问题的背景是:
fn &
fn
监视队列并tail
在作业完成时终止.这里有一些不那么简单的代码:
watch_queue(){ until [ `qstat | grep $job | wc -l` -lt 1 ]; do sleep 2 done kill -9 $pid tput setaf 7 tput setab 0 echo "Hit ENTER to return to your command prompt." tput sgr0 exit 0 } cmd="something complicated that is built at runtime" outfile="ditto" queue="selected at runtime, too" job=`echo "cd \$PBS_O_WORKDIR && $cmd >> $outfile " | qsub -q $queue -e /dev/null -o /dev/null | awk 'BEGIN { FS="." } { print $1 }'` echo "Job $job queued on $queue: $cmd" eval "tail -f -F $outfile 2>/dev/null &" pid=$! watch_queue &
当然,如果我的用户可以从单独的文件中获取作业输出,或者自己操作前景和后台之间的作业,那么对我来说会更容易,但他们不能.他们甚至不能按照脚本中的说明点击Enter以获得提示的"外观"......而且我无法打开另一个"窗口" - 他们没有显示服务器.
你要解决的问题是什么?
现在,这或多或少是一个表面问题。您仍然在 shell 中,并且提示仍然存在。只需输入另一个命令,它就会被执行。
或者,在前台运行该函数,或者如果您需要在两者之间执行其他操作,请使用wait
:
$ fn & pid=$!
$ : something else
$ wait ${pid}
Run Code Online (Sandbox Code Playgroud)
编译以下代码到文件a.out
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
/* char buf[] = "date\n"; */
char buf[] = "\n"; /* Data to write on terminal */
int i;
int fd = open(argv[1], O_WRONLY); /* Open terminal */
/* printf("fd = %d\n", fd); */
for (i = 0; i < sizeof buf - 1; i++) /* Write data */
ioctl(fd, TIOCSTI, &buf[i]);
close(fd); /* Close file descriptor */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该程序需要一个路径作为命令行参数。程序将打开该路径并向该路径写入新行。
如果此路径碰巧包含运行 bash 脚本的可写终端的文件描述符,这将导致 bash 捕获新的提示符。
修改你的shell脚本
fn(){
sleep 10
echo "Done"
./a.out /proc/$PPID/fd/0
}
fn &
Run Code Online (Sandbox Code Playgroud)
该脚本将执行一些工作(此处用 sleep 表示),然后调用之前编写的实用程序,并将参数作为父级的输入终端。父终端将收到一个新行并捕获一个新提示,并丢弃此提示上的杂散命令(如果有)。
/proc
包含所有进程的目录。文件夹名称与进程 pid 匹配。Inbuild 变量PPID
包含父进程的 pid。在该pid
目录内,有一个fd
包含打开流的目录。
0
用于输入,1
用于输出,2
用于错误。根据进程的不同,可能会有更多的开放流。我们对这里的流感兴趣0
。