Is it possible to programmatically capture stdout (and stdin) of an already running process on Linux? (Maybe redirect it to a pipe?)
It would be best if the solution worked in userspace (meaning without needing root privileges).
I've seen an answer apparently using gdb, but I'd like to do it without gdb.
EDIT: To clarify: no, I don't have access to the code, neither do I want to change the binary, I want the solution to work from a separate process. The target process is already running anyway.
From inside the process itself (assuming you can change its code in C) you might try freopen(3), perhaps as
FILE*newout = freopen("/some/path", "w", stdout);
if (!newout) { perror("freopen"); exit (EXIT_FAILURE); }
stdout = newout;
See also stdio(3). (Otherwise dup2 the STDOUT_FILENO).
From outside of the process you might perhaps play with /proc/$PID/fd/ that is dup2(2), or redirecting, or tee(1), the /proc/$PID/fd/0 for the stdin of your process $PID, the /proc/$PID/fd/1 for the stdout of your process $PID etc. See proc(5) for more.
Hmmm, note to self: after reading some other similar questions, here are some promising projects which might (?) help me find the answer:
neercs (via)
reptyr (via, via)
injcode (via, via)
If you've already started the process you can use gdb to actually redirect stdout or strace to just intercept the calls to write et.al.
If you don't want to use gdb or strace you would probably need to basically do the same thing as these do. The magic they're doing is to use the ptrace function to trace the other process. This will require that you have the right to trace the program (which also gdb and strace requires), as a normal user you can't trace programs of other users.
Linux Journal has an article about playing with ptrace that shows how you do it. One thing to note is that this will be platform dependent: you have to write the code specifically for the platform you're using, the article seems to have examples for the (32 bit) x86 platform.
Related
I'm creating some pipes and handing it over to fork()/exec()'d child process as stdout and stderr FDs. But the child program doesn't output ANSI colours.
For e.g., the gcc command can output diagnostics with colours. But when I create it as a child of my program and hand over the piped FDs it doesn't send generate colours.
With a bit of snooping around, I found it tests isatty(STDERR_FILENO) and doesn't send ANSI colour codes when it returns false. Is there a way I can make my pipes be treated as TTYs in child process?
P.S. Also, please not I'm aware of unbuffer shell command which was recommended for similar question. I am looking for C/POSIX API solution that's portable across unices. Not just Linux.
There are two answers to your question, the direct answer and the answer to your XY problem. First, the latter. Generally, programs that can output color/formatting suitable for a terminal, or plain text, choose their default based on isatty, but let you pass an explicit option to enable or disable it. For GCC, this is -fdiagnostics-color=always. This is almost surely what you should be using.
But to answer your original question, the way to do this is not to use a pipe but instead a pseudo-tty (pty). The POSIX interfaces to do this are posix_openpt, grantpt, unlockpt, and ptsname (to get the name of the device to open). But there's a much nicer non-standardized interface, openpty, that does it all for you in one call, and an accompanying forkpty that automatically forks and connects the child's stdin/out/err up to it. I would use one of these if available (they're available on glibc and musl on Linux systems, and on most/all BSD systems).
Short answer is no. Longer answer is that rather than a pipe, you could setup a pseudo-tty, and run a command in it which captures the compilers output. That is a lot of work. Man 7 pty for a detailed description.
You could take a different approach, and define your own mapping of diagnostics to colours for various commands. Please do the non-bling-addicted world a favour and provide an option to not adorn the text....
I have a problem similar to bash script flush but would appreciate confirmation and clarification:
I have a console-based, interactive perl script that writes to stdout. Along the way, it uses system() to call a C program, and its output (also to stdout) is massaged by the script and output to the user.
On Windows there have been no issues. But on Linux, in one very specific and very repeatable instance, only the trailing part of the program's message arrives to the script. Found that by adding fflushes in the C program, the issue goes away.
EDIT: Further testing reveals that a single fflush just before returning has cleared up the issue, at least for this specific instance. So this point of this post is now where the community thinks the issue is occurring, so I can avoid it in other situations in the future...
Is it the interplay between the script and the C program, both of which use stdout? Or is it that system() in perl creates a sub-shell to execute the program, and maybe the issue arises there?
If the former: is fflush the best option? Just one call seems quite reasonable in terms of overhead.
If the latter, could stdbuf somehow be used to alter the stdout behavior of the sub-shell running the program, especially if it's a program that can't be rewritten?
Thanks!
I've tested, and found the issue can be resolved with either of these approaches:
Add fflush at the end of the C program.
Run the C program without fflush using (in perl) `stdbuf -oL myprog` (I had incorrectly referenced system() before, sorry).
Some commenters refer to the fact that C should flush the buffer on exit, but CERT vulnerability FI023.C is specifically about unflushed data in stdout using C. When capturing stdout using perl tickmarks, I'm left wondering if that's a sort of redirection where this situation can occur.
How can I capture another process's output using pure C? Can you provide sample code?
EDIT: let's assume Linux. I would be interested in "pretty portable" code. All I want to do is to execute a command, capture it's output and process it in some way.
There are several options, but it does somewhat depend on your platform. That said popen should work in most places, e.g.
#include <stdio.h>
FILE *stream;
stream = popen("acommand", "r");
/* use fread, fgets, etc. on stream */
pclose(stream);
Note that this has a very specific use, it creates the process by running the command acommand and attaches its standard out in a such as way as to make it accessible from your program through the stream FILE*.
If you need to connect to an existing process, or need to do richer operations, you may need to look into other facilities. Unix has various mechanisms for hooking up a processes stdout etc.
Under windows you can use the CreateProcess API to create a new process and hook up its standard output handle to what you want. Windows also supports popen.
There's no plain C way to do this that I know of though, so it's always going somewhat dependent on platform specific APis.
Based on your edits popen seems ideal, it is "pretty portable", I don't think there's a unix like OS without it, indeed it is part of the Single Unix Specification, and POSIX, and it lets you do exactly what you want, execute a process, grab its output and process it.
If you can use system pipes, simply pipe the other process's output to your C program, and in your C program, just read the standard input.
otherprocess | your_c_program
Which OS are you using? On *nix type OS if you are process is outputting to STDOUT or STDERR you can obviously use pipes
I've a process name and I've to send a kill() signal to that process but I need its PID to call kill(). I would only like to use:
popen("pidof process_name");
as the last thing. Is there any other way to find out the process' PID? One way I could think of is to send a socket request to that process and ask to its PID.
The other way is a little too complicated for a simple code I'm writing: to do what pidof command's source code is actually doing (it uses a function call find_pid_by_name() but that's doing a lot of things).
If no simple solution is possible, I've to do this:
system("pkill <process_name>");
and check its return code. But will pkill be available for sure on all Linux machines?
You mentioned you were using linux. It isn't the cleanest solution, but you can go through every entry in /proc and check the process name in cmdline against what you are looking for.
Use sysctl - Example code
EDIT - it is available in Linux see here
Procfs reads are very cheap, many people think of iterating through /proc like they would iterating through / , its really not the case at all.
Save some time by skipping any entry that is under 1000, there's no sense in examining kernel threads. So, basically .. after opendir(), if strtoint() thinks the entry is an int , and that int is greater than or equal to 1000, just read /proc/%d/stat.
Try to avoid the urge to just resolve the 'exe' link, as that is not going to tell you the state of the process that will be receiving the signal. For instance, if the target is in state 'D' (disk sleep), you'd want to know as the signal will not be immediately delivered, or perhaps never, if the D state is perennial.
On most systems, there's going to be 70 - 120 processes to examine and you'll often find your target way before reaching the end.
You mention, "One way I could think of is to send a socket request to that process and ask to its PID." It sounds like the process you are trying to kill is a program you wrote.
If that's the case, the cannonical thing to do is to store the pid in a file (usually under /var/run, if you have access to it) while the program is running, and remove the file when the program exits. That way, detecting whether or not the program is running is as simple as
if kill -0 $(cat /var/run/myprog.pid 2>/dev/null) 2>/dev/null; then
echo Running!
else
rm -f /var/run/myprog.pid
echo "Not running."
end
Careful study of all the implications of the above code will probably teach you a lot about how PID files work. Or you can just ask for a more detailed explanation.
This seems to work fine for me.
You might want to give the full path of the process though, lest you kill a process that has a similar name.
The main advantage of this is that you can specify the signal that you want to send.
system("killall -s 9 process_name");
why not to use fcntl with F_GETOWN ?
To complete #GregRogers answers, you just need to check implementation of pidof
https://gitlab.com/procps-ng/procps/blob/master/pidof.c#L147
https://gitlab.com/procps-ng/procps/blob/master/proc/readproc.h#L288
https://gitlab.com/procps-ng/procps/blob/master/proc/readproc.c#L932
as you can see it only searches on /proc directory.
I'm writing a utility for running programs, and I need to capture unbuffered stdout and stderr from the programs. I need to:
Capture stdout and stderr to separate files.
Output needs to not be buffered (or be line buffered).
Without modifying the source of the program being run.
The problem is, when piping output to a file, the stdout stream becomes block buffered rather than line buffered. If the program crashes, the output never gets flushed, and is blank. So I need to capture stdout without buffering (or with line buffering).
I think this can be done with pty's but I'm having difficulty finding any examples that do exactly what I want (most ignore stderr). In fact, I'm not sure I've found any pty examples in C at all; most use a higher-level interface like Python's pty and subprocess modules.
Can anyone help (with code snippets or links)? Any help would be appreciated.
EDIT: I think I've solved it. The following two links were pretty helpful.
http://publib.boulder.ibm.com/infocenter/zos/v1r10/index.jsp?topic=/com.ibm.zos.r10.bpxbd00/posixopenpt.htm
http://www.gidforums.com/t-3369.html
My code is available as a repository:
https://bitbucket.org/elliottslaughter/pty
see man 7 pty
In particular:
Unix 98 pseudo-terminals
An unused Unix 98 pseudo-terminal master is opened by calling
posix_openpt(3). (This function opens the master clone device,
/dev/ptmx; see pts(4).) After performing any program-specific initializations,
changing the ownership and permissions of the slave device
using grantpt(3), and unlocking the slave using unlockpt(3)), the corresponding
slave device can be opened by passing the name returned by
ptsname(3) in a call to open(2).
And now that you know the names of the library functions such a code will need to call, you can do two useful things:
Look up their man pages
Google for example code. Since you know what keywords to use with the search engine I suspect you will have much more luck hunting down examples.