Trying to get output of an strace command with c i wrote this code slice:
int main()
{
FILE* pout;
pout = popen("strace -fp 44030 2>&1 | grep write","r");
char buff[1000];
int d1,d2;
while(1){
if(fgets(buff,1000,pout)!=NULL)
{
printf("buff=%s\n",buff);
}
else
continue;
}
pclose(pout);
}
When i run the stated command in shell i see some output (the 44030 process is a top command running in another terminal). BUT i see nothing when running my program.
Moreover when i substitute the command in popen with "strace -fp 44030 2>&1" i see output of strace command by running my program. and I've checked for problems in grep and popen with another piece of code replacing the strace with an echo command.
Where is my problem? where can i look for my error?
EDIT:
As i waited for some time now there is lots of output there... I Think this is happening because of some kind of buffering in grep command.
You just need to disable buffering in grep, which you can do using unbuffer. See here: https://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe
Related
How do you kill a running process in a bash script without killing the script?
Goal
So... I need to kill a running process to continue with the execution of my script.
Here´s a stripped down version of my script:
# Setup
echo "Use ctrl+C to stop gathering data..."
./logger
#------------------
echo "Rest..."
I need to be able to kill ./logger without killing my script
Expected vs Actual Results
I was expecting a result like this:
Use ctrl+C to stop gathering data...
^C
Rest...
but it stops when I kill the program
use ctrl+C to stop gathering data...
^C
The ./logger command is a C program that already handles the SIGINT signal (Ctrl + C) but it won't stop until it receives it.
Is there a way to stop the program without killing my script?
The C Program is not important but it looks something like this
#include <stdio.h>
#include <signal.h>
int flag = 1;
void handler(int i)
{
flag = 0;
}
int main(int argc, char** argv)
{
signal(SIGINT, handler);
while(flag)
{
usleep(10000);
}
}
If you type control-C at the terminal where the script is running, the signal goes to all the processes — the logger program and the script. And the script terminates because you've not told it to ignore signals while the logger is run. You can do that using the trap command but you'll need to undo the trapping before running the C program. See the Bash manual on Signals too.
For example, I have a program dribbler that generates messages, one every second by default, but it is configurable. I'm using it as a surrogate for your ./logger program. The -m options specifies the message; the -n option requests that the messages are numbered, and the -t option specifies output to standard output (instead of a file which it writes to by default).
#!/bin/bash
#
# SO 6418-0134
program="dribbler -t -n -m Hello"
echo "About to run '$program' command"
trap "" 2
(trap 2; $program)
echo "Continuing after '$program' exits"
sleep 1
echo "But not for long"
The sub-shell is necessary. When I run that script (trapper.sh), I get, for example:
$ bash trapper.sh
About to run 'dribbler -t -n -m Hello' command
0: Hello
1: Hello
2: Hello
3: Hello
^CContinuing after 'dribbler -t -n -m Hello' exits
But not for long
$
Incidentally, POSIX defines a command logger that writes messages using the syslog() function(s) to the syslog daemon.
It might also be worth reviewing the Q&A about Sending SIGINT to forked exec process which runs a script does not kill it, especially the accepted answer and its links to Q&A on other Stack Exchange sites, as it matters that you and I both executed a C program, not a shell script.
I've been stuck on this for a while now, is it possible to redirect stdout to two different places? I am writing my own shell for practice, and it can currently run commands like ps aux | wc -l or ps aux | wc -l > output.file. However, when I try to run ps aux > file.out | wc -l, the second command does not receive the input from the first.
In the last example, the first command would be run in a child process that would output to one end of the pipe. The logic is similar to what follows:
close(stdout);
dup2(fd[1], STDOUT_FILENO);
//If a file output is also found
filewriter = open(...);
dup2(filewriter, STDOUT_FILENO);
//Execute the command
Normal UNIX shells don't work with that syntax either. UNIX (and some other OSs) provides the tee[1] command to send output to a file and also stdout.
Example:
ps aux | tee file.out | wc -l
[1] See http://en.wikipedia.org/wiki/Tee_(command)
The tee command does just that in UNIX. To see how to do it in straight C, why not look at tee's source code?
I want to get the Output of multiple strace calls in one file,
but i do not know how.
At the moment i am using:
strace -o tmpfile, but this just puts the output of one file in and then overrites the file with the new output.
Has anyone an idea, how to do this?
I hope this is no dumb question.
Thanks in advance.
Under the bash shell use the following command
strace -o >(cat >>outputfile) command [args] ...
This will pass to the -o flag an argument that will appear like a file, but will be instead a file descriptor to the standard input of the
cat >>outputfile
process. This process will append its input to the specified output file.
Instead of strace -o somefile command, can you just do strace command >> somefile? Alternatively, assuming a similar version of strace, my manual for strace indicates this should work: strace -o "|tail -a somefile" command (the -o "|command" functionality is implemented by strace itself, not by the shell).
I could not manage to do this via the call itself (in the Android Shell).
I just read through all files and write them to one Log file.
This solution slows the whole process down, but was the only solution I found.
The strace output is on stderr, strace 2>> outfile did the trick for me. If you invoke strace as single command you have to call it like this: adb -e shell "strace -p pid 2>> file"
How to get a process name from his pid ?
For example I execute cat file1.txt, but I want to figure out that cat command and its arguments since its pid in the system. Is there a struct to determine it or something similar? Any idea?
There is not any general way to do this unix. Each OS has different ways to handle it and some are very hard. You mention Linux though. With Linux, the info is in the /proc filesystem. To get the command line for process id 9999, read the file /proc/9999/cmdline.
On linux, you can look in /proc/. Try typing man proc for more information. The contents of /proc/$PID/cmdline will give you the command line that process $PID was run with. There is also /proc/self for examining yourself :)
An alternative (e.g. on Mac OS X) is to use libproc. See libproc.h.
POSIX C does NOT support give a standard API for getting the process name by PID.
In linux, you can get the name by LINUX Proc API: /proc/$PID/cmdline. And the code looks like these:
const char* get_process_name_by_pid(const int pid)
{
char* name = (char*)calloc(1024,sizeof(char));
if(name){
sprintf(name, "/proc/%d/cmdline",pid);
FILE* f = fopen(name,"r");
if(f){
size_t size;
size = fread(name, sizeof(char), 1024, f);
if(size>0){
if('\n'==name[size-1])
name[size-1]='\0';
}
fclose(f);
}
}
return name;
}
To get the process name of a process id say 9000 use this command:
ps -p 9000 -o comm=
While this question has been answered, I'd like to add my 2 cents.
In my case, when process 1111 creates process 22222 via pipe (at least this is what I heard), /proc/2222/cmdline does not give correct process name, but instead gives something like 1111_1. I have to use /proc/2222/comm to get the correct process name.
Use the below command in Linux
ls -l /proc/[pid]/exe
It will give the name of the process/application name
ps --pid <pid> -o comm h :
This command gives executable file name. For example if you run a script name.sh, then the above command gives output as bash
ps --ppid <pid> -o comm h:
This command gives the output as name
I'm using popen to run a system script, like so:
snprintf(cmd, MAX_PATH, "/myscript -q | grep -i %s", deviceName);
FILE *res = popen(cmd, "r");
If the script is not found, the program carries on its merry way. However, a "file or directory not found" message is displayed, which seems like an error even though in my intended usage it isn't.
Is there a way to silence this message, or should I just call ls | grep -i myscript before running this line?
Assuming your /bin/sh is a POSIX shell, or a reasonably recent Bourne shell variant, you can redirect standard output within the command before executing the actual command. You only need to prepend exec 2>/dev/null ; before the command you wish to execute.
Here is how I'd personally do this:
/* Shell syntax for redirecting standard error to /dev/null, to
* silence any errors. If /bin/sh does not support this, you can
* simply replace it with an empty string.
*/
#define POPEN_STDERR_NULL "exec 2>/dev/null ;"
...
snprintf(cmd, MAX_PATH, POPEN_STDERR_NULL "/myscript -q | grep -i -e '%s'", deviceName);
FILE *res = popen(cmd, "r");
The popen() command uses /bin/sh internally to run the specified command. The above works for all /bin/sh variants I can test, including Linux and SunOS 5.10, so it should be quite portable. (In other words, dash, bash, and SunOS 5.10 sh all work fine with it.)
Since you'll need to recompile the application for any nonstandard systems, you can always edit the macro to omit the prefix. (You can easily add a test to Makefile magic to automatically omit it if necessary, if you ever find such a system.)
Note that I modified the parameter substitution in the snprintf() call. It will work for any deviceName that does not contain a single quote. Any single quotes in deviceName should be replaced with the string '"'"' before the snprintf() call.
Questions?
I'm not too sure if you can stifle the message. The error is a standard Linux error which is printed onto the standard error stream. You can keep FD '2' which is the file descriptor for Standard error. So maybe you can close this FD.
However, I must warn you that this will prevent any errors from being printed for the rest of your program.
A better way would be to do this:
snprintf(cmd, MAX_PATH, "/myscript -q | grep -i %s 2> dummyfile", deviceName);
This will redirect the error to a dummy file which you delete immediately.
So exercise caution and decide what you would like to do...
Cheers,
VSN