Redirect running process STDOUT/STDERR to SSH STDOUT using GDB - linux

I have a process running on an embedded system (linux).
its STDOUT/STDERR is the console which is on a serial port.
I would like to redirect its ouputs (standard and error) to that of an SSH session.
I have read you can do similar operations with GDB, but I don't know how you would redirect to the SSH session's STDOUT/STDERR instead of to a file.
I can't do it to a file because of low disk resources. Also I have seen some examples using a named pipe, but I don't have mkfifo command available. I do have GDB.
Also, assuming this is possible, would the process terminate when I close the SSH session? If so, could I redirect back before I do?
Thanks.

You can do it as long as you can call libc functions from gdb.
#ssh root#embedded
Query daemon output location:
# ls -l /proc/`pidof daemon`/fd/1
/proc/13202/fd/1 -> /dev/null
It can be not null, it can point to some other console or even some pipe or file, store this location somewhere. Query your ssh session output location:
# ls /proc/self/fd/1 -l
lrwx------ 1 root root 64 дек. 15 16:51 /proc/self/fd/1 -> /dev/pts/9
or simply call tty if you have it.
Now goes the work:
# gdb -p `pidof daemon`
..
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) call open("/dev/pts/9",2,0)
$1 = 0x3
(gdb) call dup2(3,2)
$2 = 0x2
(gdb) call dup2(3,1)
$3 = 0x1
(gdb) quit
Detaching from program: /root/daemon, process 13202
daemon output/errorput
Repeat the same steps before exit from ssh session, just replace /dev/pts/9 with initial output location in the open syscall.

Related

Monitoring all running process using strace in shell script

I want to monitor all the running processes using strace and when a process ends the output of the strace should be sent to a file.
And how to find every running proc PID. I also want to include process name in the output file.
$ sudo strace -p 1725 -o firefox_trace.txt
$ tail -f firefox_trace.txt
1725 would be the PID of the proccess you want to monitor (you can find the PID with "ps -C firefox-bin", for firefox in the example)
And firefox_trace.txt would be the output file !
The way to got would be to find every running proc PID, and use the command to write them in the output file !
Considering the doc,
-p pid
Attach to the process with the process ID pid and begin tracing. The
trace may be terminated at any time by a keyboard interrupt signal (
CTRL -C). strace will respond by detaching itself from the traced
process(es) leaving it (them) to continue running. Multiple -p options
can be used to attach to up to 32 processes in addition to command
(which is optional if at least one -p option is given).
Use -o to store the output to the file, or 2>&1 to redirect standard error to output, so you can filter it (grep) or redirect it into file (> file).
To monitor process without knowing its PID, but name, you can use pgrep command, e.g.
strace -p $(pgrep command) -o file.out
where command is your name of process (e.g. php, Chrome, etc.).
To learn more about parameters, check man strace.

Is there a way to flush stdout of a running process

I have a long-running process with stdout redirected to a file. E.g.:
./my-script.sh > file.txt &
Part of the stdout is still cached, but I would like to flush it to the file, to see the results earlier. Is there a way to do it?
The caching is handled by the libc. You can use the stdbuf command to change the buffer size:
stdbuf -o0 ./my-script.sh > file.txt &
-o0 sets the buffer size for stdout to 0. Probably you also want -e0 for stderr.
You can inspect the /proc/ filesystem and alter the file descriptor of stdout. For example:
gerard#droole ~$ bash -c '
while [ true ]; do echo "."; sleep .5; done
' > ./myfile.txt &
[1] 3816
gerard#droole ~$ ls -la /proc/3816/fd/1
l-wx------ 1 gerard gerard 64 May 30 14:55 /proc/3816/fd/1 -> /home/gerard/myfile.txt
You can see that stdout is symlinked to the file I specified on the command line. If you want to change it, you can simply link it to something else.
If you want to reroute this output, you can start a tee process, symlink the stdout of the process you're watching to a the stdin of the new process. You can reroute basically anything you want this way.
However, this is not very stable, as your programs output will be broken if you do not carefully restore its stdout file descriptor before the tee process is terminated.
But it is not impossible ;)

gdb remote debugging of c++ process started via ssh: how to redirect stdin

First, some background. I run a program by starting a process on a remote_host using ssh:
ssh -T remote_host "cd ~/mydir && ~/myprogram" < input.txt
The program, myprogram, reads stdin, which is attached to a local file input.txt.
Now, I need to remotely debug this program under gdb. If there was no stdin redirection, i.e. < input.txt, I would be able to do this using gdb's target remote, something like this (at gdb prompt):
(gdb) target remote | ssh -T remote_host gdbserver - myprogram
However, in the above example, I don't know how to attach myprogram's stdin to input.txt.
Is there something that would do the trick?
gdbserver doesn't read from stdin, so the program it invokes will have unfettered access to stdin. You should be able to do this:
ssh -T remote_host "cd ~/mydir && gdbserver :1234 ~/myprogram" < input.txt
where 1234 is an unused port. Then,
(gdb) target remote remote_host:1234
A drawback with this is that the gdb-gdbserver TCP connection won't be encrypted.

How to start a stopped process in Linux

I have a stopped process in Linux at a given terminal. Now I am at another terminal. How do I start that process. What kill signal would I send. I own that process.
You can issue a kill -CONT pid, which will do what you want as long as the other terminal session is still around. If the other session is dead it might not have anywhere to put the output.
In addition to #Dave's answer, there is an advanced method to redirect input and output file descriptors of a running program using GDB.
A FreeBSD example for an arbitrary shell script with PID 4711:
> gdb /bin/sh 4711
...
Attaching to program: /bin/sh, process 4711
...
(gdb) p close(1)
$1 = 0
(gdb) p creat("/tmp/testout.txt",0644)
$2 = 1
(gdb) p close(2)
$3 = 0
(gdb) p dup2(1,2)
$4 = 2
EDIT - explanation: this closes filehandle 1, then opens a file, which reuses 1. Then it closes filehandle 2 and duplicates filehandle 1 to 2.
Now this process' stdout and stderr go to indicated file and are readable from there. If stdin is required, you need to p close(0) and then attach some input file or PIPE or smth.
For the time being, I could not find a method to remotely disown this process from the controlling terminal, which means that when the terminal exits, this process receives SIGHUP signal.
Note: If you do have/gain access to the other terminal, you can disown -a so that this process will continue to run after the terminal closes.

How to redirect output of an already running process [duplicate]

This question already has answers here:
Redirect STDERR / STDOUT of a process AFTER it's been started, using command line?
(8 answers)
Closed 6 years ago.
Normally I would start a command like
longcommand &;
I know you can redirect it by doing something like
longcommand > /dev/null;
for instance to get rid of the output or
longcommand 2>&1 > output.log
to capture output.
But I sometimes forget, and was wondering if there is a way to capture or redirect after the fact.
longcommand
ctrl-z
bg 2>&1 > /dev/null
or something like that so I can continue using the terminal without messages popping up on the terminal.
See Redirecting Output from a Running Process.
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().
You can also do it using reredirect (https://github.com/jerome-pouiller/reredirect/).
The command bellow redirects the outputs (standard and error) of the process PID to FILE:
reredirect -m FILE PID
The README of reredirect also explains other interesting features: how to restore the original state of the process, how to redirect to another command or to redirect only stdout or stderr.
The tool also provides relink, a script allowing to redirect the outputs to the current terminal:
relink PID
relink PID | grep usefull_content
(reredirect seems to have same features than Dupx described in another answer but, it does not depend on Gdb).
Dupx
Dupx is a simple *nix utility to redirect standard output/input/error of an already running process.
Motivation
I've often found myself in a situation where a process I started on a remote system via SSH takes much longer than I had anticipated. I need to break the SSH connection, but if I do so, the process will die if it tries to write something on stdout/error of a broken pipe. I wish I could suspend the process with ^Z and then do a
bg %1 >/tmp/stdout 2>/tmp/stderr
Unfortunately this will not work (in shells I know).
http://www.isi.edu/~yuri/dupx/
Screen
If process is running in a screen session you can use screen's log command to log the output of that window to a file:
Switch to the script's window, C-a H to log.
Now you can :
$ tail -f screenlog.2 | grep whatever
From screen's man page:
log [on|off]
Start/stop writing output of the current window to a file "screenlog.n" in the window's default directory, where n is the number of the current window. This filename can be changed with the 'logfile' command. If no parameter is given, the state of logging is toggled. The session log is appended to the previous contents of the file if it already exists. The current contents and the contents of the scrollback history are not included in the session log. Default is 'off'.
I'm sure tmux has something similar as well.
I collected some information on the internet and prepared the script that requires no external tool: See my response here. Hope it's helpful.

Resources