0

I have a process running on the server, for some reason my client system got restarted so i login again to the server using a terminal.

The process is running as expected but the status of the process which is continously promted on the terminal disappear for obvious reason (because i am on another terminal now).

Is there any way so that i can bring the STDOUT of my running process to the current terminal ?

Thank you.

abbasi_ahsan
  • 340
  • 1
  • 11
  • Possible duplicate of [How to redirect output of an already running process](https://stackoverflow.com/questions/1323956/how-to-redirect-output-of-an-already-running-process) – Pankaj Singhal Jul 04 '19 at 08:25

2 Answers2

0

See This answer.

Firstly I run the command cat > foo1 in one session and test that data from stdin is copied to the file. Then in another session I redirect the output.

Firstly find the PID of the process:

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

Now check the file handles it has open:

$ 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

Now run 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

The p command in GDB will print the value of an expression, an expression can be a function to call, it can be a system call… So I execute a close() system call and pass file handle 1, then I execute a creat() system call to open a new file. The result of the creat() was 1 which means that it replaced the previous file handle. If I wanted to use the same file for stdout and stderr or if I wanted to replace a file handle with some other number then I would need to call the dup2() system call to achieve that result.

For this example I chose to use creat() instead of open() because there are fewer parameter. The C macros for the flags are not usable from GDB (it doesn’t use C headers) so I would have to read header files to discover this – it’s not that hard to do so but would take more time. Note that 0600 is the octal permission for the owner having read/write access and the group and others having no access. It would also work to use 0 for that parameter and run chmod on the file later on.

After that I verify the result:

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

Typing more data in to cat results in the file /tmp/foo3 being appended to.

If you want to close the original session you need to close all file handles for it, open a new device that can be the controlling tty, and then call setsid().

Pankaj Singhal
  • 15,283
  • 9
  • 47
  • 86
0

Use following script to change std out of any process.

This script attaches gdb and change file descriptor of process, detaches gdb and process continues.

Usage: <script_path> <process_id> <optional: output file>

If output file is not specified, output is redirected to current terminal

#!/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