How to get Shell script output in Linux C program
1. Preface
The Unix world has a famous saying: "A line of shell script is better than Mangyo C program", although this sentence is somewhat exaggerated, but it is undeniable that the use of scripts can greatly simplify some of the programming work. For example, to implement a ping program to test the connectivity of the network, the implementation of the PING function needs to write the 200~300 line code, why not directly call the System ping command? Shell commands are typically invoked in a program through the system function. However, the system function returns only if the command succeeds, and we may need to get the result of the shell command output on the console. For example, if execution fails after the external command ping is executed, we want to get the return information for the ping.
2. Using temporary files
The first idea is to redirect the command output to a temporary file, read the temporary file in our application, get the result of the external command execution, and the code looks like this:
Copy CodeThe code is as follows:
#define Cmd_str_len 1024
int Mysystem (char* cmdstring, char* tmpfile)
{
Char Cmd_string[cmd_str_len];
Tmpnam (tmpfile);
sprintf (cmd_string, "%s >%s", cmdstring, tmpfile);
return system (cmd_string);
}
This use of temporary files as a bridge between the application and external commands, in the application need to read the file, and then delete the temporary file, the more cumbersome, the advantage is simple, easy to understand. Is there a way to not use temporary files?
3. Using Anonymous Pipelines
In the <<unix environment Advanced Programming >> a book gives an example of the output of program results to a pager through an anonymous pipeline, so it is thought that we can also connect the results of external commands to the application through a pipeline. The method is to fork a child process, create an anonymous pipe, execute the shell command in the child process, and set its standard output to the input of the anonymous pipe, and the parent process reads from the pipe to get the output of the shell command, the code is as follows:
Copy CodeThe code is as follows:
/** * Enhanced system function to return the output of the system call *
* @param [in] cmdstring call the command string of an external program or script
* @param [out] buf returns the buffer of the result of the external command
* @param [in] len buffer buf length
* * @return 0: Success; -1: Failure */
int Mysystem (char* cmdstring, char* buf, int len)
{
int fd[2]; pid_t pid;
int n, Count;
memset (buf, 0, Len);
if (pipe (FD) < 0)
return-1;
if ((PID = fork ()) < 0)
return-1;
else if (PID > 0)/*/Parent Process */
{
Close (fd[1]); /* Close Write End */
Count = 0;
while ((n = read (fd[0], buf + count, len)) > 0 && count > Len)
Count + = n;
Close (fd[0]);
if (Waitpid (PID, NULL, 0) > 0)
return-1;
}
else/* Child process */
{
Close (fd[0]); /* Close Read end */
if (fd[1]! = Stdout_fileno)
{
if (Dup2 (fd[1], stdout_fileno)! = Stdout_fileno)
{
return-1;
}
Close (fd[1]);
}
if (Execl ("/bin/sh", "sh", "-C", Cmdstring, (char*) 0) = = =-1)
return-1;
}
return 0;
}
4. Using Popen
In the process of learning UNIX programming, the discovery system also provides a popen function, which can be very simple to process the call shell, its function prototype is as follows:
FILE *popen (const char *command, const char *type);
The function is to create a pipeline, fork a process, and then execute the shell, and the shell's output can be obtained by reading the file. In this way, it is recommended to avoid creating temporary files and not being limited by the number of output characters.
Popen executes external programs using FIFO pipelines.
Copy CodeThe code is as follows:
#include <stdio.h>
FILE *popen (const char *command, const char *type);
int Pclose (FILE *stream);
Popen the input/output direction of the command via Type R or W, R and W are relative command pipes. R means the command is read in from the pipe, and W means that the command is output by the pipeline to its stdout,popen to return a file stream pointer to the FIFO pipeline. The pclose is used to close the pointer after the end of use.
Let's look at an example:
Copy CodeThe code is as follows:
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main (void)
{
FILE *stream;
FILE *wstream;
Char buf[1024];
memset (buf, '/0 ', sizeof (BUF));//Initialize buf, lest it be garbled to the file
stream = Popen ("Ls-l", "R"); Reads the output of the "ls-l" command through the pipe ("r" parameter) to the file* stream
Wstream = fopen ("Test_popen.txt", "w+"); Create a new writable file
Fread (buf, sizeof (char), sizeof (BUF), stream); Reads the data stream just file* stream into buf
Fwrite (buf, 1, sizeof (BUF), wstream);//writes data from BUF to the stream corresponding to file *wstream
Pclose (stream);
Fclose (Wstream);
return 0;
}
[Email protected] src]# gcc popen.c
[Email protected] src]#./a.out
[email protected] src]# cat Test_popen.txt
Total 128
-rwxr-xr-x 1 root Root 5558 09-30 11:51 a.out
-rwxr-xr-x 1 root root 542 09-30 00:00 child_fork.c
-rwxr-xr-x 1 root root 480 09-30 00:13 execve.c
-rwxr-xr-x 1 root root 1811 09-29 21:33 fork.c
-rwxr-xr-x 1 root root 162 09-29 18:54 GETPID.C
-rwxr-xr-x 1 root root 1105 09-30 11:49 popen.c
-rwxr-xr-x 1 root root 443 09-30 00:55 system.c
-rwxr-xr-x 1 root root 0 09-30 11:51 test_popen.txt
-rwxr-xr-x 1 root root 4094 09-30 11:39 test.txt
5. Summary
Statistical data show that the defect rate of the code is certain, regardless of the language used. Linux provides a lot of utilities and scripts to invoke tools and scripts in the program, which can undoubtedly simplify the program, thereby reducing the number of defects in the code. The Linux shell script is also a powerful tool, and we can script it as needed, and then invoke the custom script in the program.
How to get Shell script output in Linux C program