如何使正在运行的后台进程成为前台?

时间:2019-07-04 07:40:08

标签: server terminal stdout

我有一个正在服务器上运行的进程,由于某种原因,我的客户端系统重新启动,因此我使用终端再次登录到服务器。

该进程正在按预期方式运行,但是由于明显的原因(因为我现在在另一个终端上),持续在终端上提示的进程状态消失了。

有什么办法可以将正在运行的进程的STDOUT带到当前终端吗?

谢谢。

2 个答案:

答案 0 :(得分:0)

请参见 This answer

  

首先,我在一个会话中运行命令cat > foo1,并测试将来自stdin的数据复制到文件中。然后在另一个会话中,我重定向输出。

     

首先找到该进程的PID:

$ ps aux | grep cat
rjc 6760 0.0 0.0 1580 376 pts/5 S+ 15:31 0:00 cat
     

现在检查文件句柄是否已打开:

$ ls -l /proc/6760/fd
total 3
lrwx—— 1 rjc rjc 64 Feb 27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 Feb 27 15:32 1 -> /tmp/foo1
lrwx—— 1 rjc rjc 64 Feb 27 15:32 2 -> /dev/pts/5
     

现在运行GDB:

$ gdb -p 6760 /bin/cat
GNU gdb 6.4.90-debian

[license stuff snipped]

Attaching to program: /bin/cat, process 6760

[snip other stuff that's not interesting now]

(gdb) p close(1)
$1 = 0
(gdb) p creat("/tmp/foo3", 0600)
$2 = 1
(gdb) q
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: /bin/cat, process 6760
     

GDB中的p命令将打印表达式的值,表达式可以是要调用的函数,可以是系统调用……所以我执行了close()系统调用并传递文件句柄1,然后执行creat()系统调用以打开一个新文件。 creat()的结果为1,表示它替换了先前的文件句柄。如果我想对stdout和stderr使用相同的文件,或者想用其他数字替换文件句柄,则需要调用dup2()系统调用来实现该结果。

     

在此示例中,我选择使用creat()而不是open(),因为参数较少。这些标志的C宏无法从GDB使用(它不使用C标头),因此我必须阅读标头文件才能发现这一点-这样做并不难,但会花费更多时间。请注意,0600是具有读/写访问权限的所有者以及该组和其他没有访问权限的所有者的八进制权限。为该参数使用0并稍后在文件上运行chmod也是可行的。

     

之后,我验证结果:

ls -l /proc/6760/fd/
total 3
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 2008-02-27 15:32 1 -> /tmp/foo3 <====
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 2 -> /dev/pts/5
     

cat中输入更多数据会导致文件/tmp/foo3被附加到文件中。

     

如果要关闭原始会话,则需要为其关闭所有文件句柄,打开一个可以作为控制tty的新设备,然后调用setsid()

答案 1 :(得分:0)

使用以下脚本将std更改为任何进程。

此脚本附加gdb并更改进程的文件描述符,分离gdb并继续执行进程。

用法:<脚本路径> <进程ID> <可选:输出文件>

如果未指定输出文件,则将输出重定向到当前终端

#!/bin/sh

filename=`tty`
if [ -z "$2" ]; then
    filename=`tty`
else
    file_abs_path=`echo $2 | grep "^/.*"`
    if [ -z "$file_abs_path" ]; then
        filename="`pwd`/$2"
    else
        filename=$2
    fi
fi

original_terminal=`file /proc/$1/fd/1 | grep -o "symbolic.*" | grep -o "\/[^ ']*"`
echo "Original stdout: $original_terminal"
echo "" > $1.temp
echo "p fileno(fopen("\"$filename\"", "\""w"\""))" >> $1.temp
echo 'call dup2($1, 1)' >> $1.temp
echo 'call dup2($1, 2)' >> $1.temp
echo "q" >> $1.temp


gdb -p $1  -x $1.temp < /dev/null >& /dev/null
echo "New stdout: $filename"
rm -rf $1.temp