Running Unix or Linux Commands from C, Java, Python and getting the Output String and Status code

Thursday, March 19, 2009

I saw some comments where people asked about running Unix/Linux commands from C and Java, its quite easy to do that, although I did it long time before in C, but executing UNIX commands from java and python is something which I do quite often and thought its worth posting these simple code here, doing it from java may sound quite simple, but I really tinkered with the java InputStreams and Readers for sometime before getting it right.

I tried these code from Solaris and Linux, the C and java code will work for Windows executables and commands (from java, you need a different way to execute DOS commands, but you can try other executables), the python solution is quite simple using the commands module which has methods to execute and fetch the command output/status code from UNIX, though the commands module cannot be used to run Windows executables.

All the three programs take the Unix command to be executed as a command line parameter and fetches the command output and status in a similar format, I will go from the toughest to the easiest, from C to java to python.

1. Running Unix or Linux commands from C
2. Running Unix or Linux commands from Java
3. Running Unix or Linux commands from Python

1. Running Unix or Linux commands from C

unix_command.c
 1: /*
2: * unix_command.c
3: * Author: S.Prasanna
4: * @version 1.00
5: */
6:
7: #include <stdio.h>
8: #include <stdlib.h>
9:
10: int main(int argv, char ** argc) {
11:
12: if (argv != 2) {
13: printf("Usage: unix_command \"COMMAND TO BE EXECUTED IN QUOTES\"");
14: exit(1);
15: }
16:
17: char *COMMAND = argc[1],*readLine, *tmp, *commandResult = "";
18: FILE * fp;
19: int status;
20:
21: fp = popen(COMMAND, "w");
22:
23: if (fp == NULL) {
24: perror("Command execution failed");
25: exit(1);
26: }
27:
28: printf("Printing the command output....");
29: while ((fscanf(fp, "%s", &readLine)) != EOF) {
30: tmp = (char *) realloc(commandResult, strlen(readLine));
31: commandResult = tmp;
32: strcpy(commandResult, readLine);
33: }
34: printf("\nCommand %s output = %s", COMMAND, commandResult);
35: status = pclose(fp);
36: printf ("Command %s exit status code = %d\n", COMMAND, status);
37: return status;
38: }
Output:

bash-3.00# ./unix_command.out "ls -l"
Printing the command output....
Command ls -l output = total 28
-rwxrwxrwx 1 root root 954 Mar 18 22:39 unix_command.c
-rw-r--r-- 1 root root 1598 Mar 18 21:35 unix_command.class
-rwxrwxrwx 1 root root 1321 Mar 18 21:33 unix_command.java
-rwxr-xr-x 1 root root 7408 Mar 18 22:40 unix_command.out
-rw-r--r-- 1 root root 438 Mar 18 21:33 unix_command.py
Command ls -l exit status code = 0
bash-3.00#

Explanation:

The C Code execution is quite simple, the popen() call in line 21 takes the process name or UNIX command to be executed with parameters in the form of a string and returns a file pointer (line 21) through which the process's input stream can be accessed and read (using fscanf function in line 29). The realloc() function (line 30) is used to expand the string array used to fetch the process's output as and when the input stream is read and the process's exit status code is fetched from the plose() call (line 35).

2. Running Unix or Linux commands from Java

unix_command.java
 1: /*
2: * unix_command.java
3: * Author: S.Prasanna
4: * @version 1.00
5: */
6:
7: import java.io.InputStream;
8:
9: public class unix_command {
10:
11: public static void main (String args[]) {
12: if (args.length < 1) {
13: System.out.println("Usage: java unix_command \"COMMAND TO BE EXECUTED\"");
14: System.exit(1);
15: }
16:
17: String COMMAND = args[0];
18:
19: for (int i = 1; i < args.length; i++) {
20: COMMAND = COMMAND + " " + args[i];
21: }
22:
23: InputStream in = null;
24: Process p = null;
25:
26: try {
27:
28: StringBuffer commandResult = new StringBuffer();
29: String line = null;
30: int readInt;
31:
32: p = Runtime.getRuntime().exec(args, null);
33: int returnVal = p.waitFor();
34: if (returnVal == 0)
35: in = p.getInputStream();
36: else
37: in = p.getErrorStream();
38:
39: while ((readInt = in.read()) != -1)
40: commandResult.append((char)readInt);
41:
42: System.out.println("Command " + COMMAND + " output = \n" + commandResult.toString());
43: System.out.println("Command " + COMMAND + " exit status = " + returnVal);
44: in.close();
45: } catch (Exception e) {
46: System.out.println("An exception occured while executing command " + COMMAND);
47: e.printStackTrace();
48: }
49: }
50: }
bash-3.00# java unix_command ls -l
Command ls -l output =
total 28
-rwxrwxrwx 1 root root 954 Mar 18 22:39 unix_command.c
-rw-r--r-- 1 root root 1598 Mar 18 21:35 unix_command.class
-rwxrwxrwx 1 root root 1321 Mar 18 21:33 unix_command.java
-rwxr-xr-x 1 root root 7408 Mar 18 22:40 unix_command.out
-rw-r--r-- 1 root root 438 Mar 18 21:33 unix_command.py

Command ls -l exit status = 0
bash-3.00#

Explanation:

The Runtime class's exec method (through the Runtime's static instance) takes an array of String with the process or unix command's name and its arguments and returns a Process object (line 32) whose input stream can be accessed and read through a standard java InputStream (line 35). The Process object's waitFor method (line 33) returns the exit value of the subprocess and for non successful return values (return value other than zero), the Process's ErrorStream is accessed to read the error message (line 37).

3. Running Unix or Linux commands from Python

unix_command.py
1.  #
2. # Executing UNIX commands from python
3. # unix_command.py
4. # Author: S.Prasanna
5. #
6.
7. import commands
8. import sys
9.
10. if len(sys.argv) != 2:
11. print "Usage: unix_command \"COMMAND TO BE EXECUTED IN QUOTES\""
12. sys.exit(1)
13.
14. COMMAND = sys.argv[1]
15.
16. command_result = commands.getstatusoutput(COMMAND)
17. print "Command %s exit status code = %s" % (COMMAND, command_result[0])
18. print "Command %s command result = %s" % (COMMAND, command_result[1])
Output:

bash-3.00# python unix_command.py "ls -l"
Command ls -l exit status code = 0
Command ls -l command result = total 28
-rwxrwxrwx 1 root root 954 Mar 18 22:39 unix_command.c
-rw-r--r-- 1 root root 1598 Mar 18 21:35 unix_command.class
-rwxrwxrwx 1 root root 1321 Mar 18 21:33 unix_command.java
-rwxr-xr-x 1 root root 7408 Mar 18 22:40 unix_command.out
-rw-r--r-- 1 root root 438 Mar 18 21:33 unix_command.py
bash-3.00#

Explanation:

The python solution is quite simple, the commands module's getstatusoutput method (line 16) fetches the UNIX command's exit status code and the command output string in a tuple which is printed (line 17 and 18).

10 comments:

srid said...

`commands' module is being deprecated. use subprocess.

Prasanna Seshadri said...

Hi,

Thanks, need to change that.

Anonymous said...

hi, thanks for this, it is useful.

Anonymous said...

Hi Thanks for this.

A problem I am facing with the java piece of code is when I issue the command ps -aef. The waitFor()doesn't finish, It just waits there. It works fine without the option 'e'. Any comments on this ?

Sunil said...

Hi, Prasanna Seshadri

Thanks, I have problem running find command from java...

StringBuffer args=new StringBuffer("find /sent/").append(new File(file.getParent()).getName());
args.append(" -exec grep -q '").append(instanceIdentifier).append("' '{}' \\;");//.append(" -print | xargs ls -ld");

System.out.println(args.toString());
p = Runtime.getRuntime().exec(args.toString());

and here is the output...
/usr/bin/find: missing argument to `-exec'

any idea how to execute this???

Sunil said...

sorry missed this..this is find command tht I am trying use

find /sent/2009-02-24 -exec grep -q '90224225844431225922' '{}' \;

Thanks, Sunil

Prasanna Seshadri said...

Will check this one out and let you know, little busy with other stuff.

Greg said...

hi, have you ventured to add syntax highlighting to the file_line_numbers.py ?

curious what the best way to integrate it would be... convert code from the html tmp or parse during line number assiging... python or geshi/pastebin?
if you don't mind - let me know gmilby at gmail.com
thank you

Sudharsan said...

Hi all...if anyone have the code for getting a file from the unix server and printing the contents of the file in java.... Please help me with this.......

nanda said...

hi,
i have an issue.
if i want to give input to commands, say
"dig something.com"..

now how do i pass variables to the dig command?


Copyright © 2016 Prasanna Seshadri, www.prasannatech.net, All Rights Reserved.
No part of the content or this site may be reproduced without prior written permission of the author.