How to Run a Bash Script from C++ Program

How to execute bash commands from C?

Use system():

#include <stdlib.h>
int status = system("gzip foo");

See the man page (man 3 system) for more detailed information on how to use it.

By the way, this question already has an answer here: How do I execute external program within C code in linux with arguments?

How to execute a shell script from C in Linux?

It depends on what you want to do with the script (or any other program you want to run).

If you just want to run the script system is the easiest thing to do, but it does some other stuff too, including running a shell and having it run the command (/bin/sh under most *nix).

If you want to either feed the shell script via its standard input or consume its standard output you can use popen (and pclose) to set up a pipe. This also uses the shell (/bin/sh under most *nix) to run the command.

Both of these are library functions that do a lot under the hood, but if they don't meet your needs (or you just want to experiment and learn) you can also use system calls directly. This also allows you do avoid having the shell (/bin/sh) run your command for you.

The system calls of interest are fork, execve, and waitpid. You may want to use one of the library wrappers around execve (type man 3 exec for a list of them). You may also want to use one of the other wait functions (man 2 wait has them all). Additionally you may be interested in the system calls clone and vfork which are related to fork.

fork duplicates the current program, where the only main difference is that the new process gets 0 returned from the call to fork. The parent process gets the new process's process id (or an error) returned.

execve replaces the current program with a new program (keeping the same process id).

waitpid is used by a parent process to wait on a particular child process to finish.

Having the fork and execve steps separate allows programs to do some setup for the new process before it is created (without messing up itself). These include changing standard input, output, and stderr to be different files than the parent process used, changing the user or group of the process, closing files that the child won't need, changing the session, or changing the environmental variables.

You may also be interested in the pipe and dup2 system calls. pipe creates a pipe (with both an input and an output file descriptor). dup2 duplicates a file descriptor as a specific file descriptor (dup is similar but duplicates a file descriptor to the lowest available file descriptor).

linux script running c program

Get rid of the backticks, the chmod, and the echo. All you need to do is run gcc, then run your program.

#!/bin/bash
gcc odd.c -o odd222
./odd222

It'd also be good to only try to run the program if it compiles successfully. You can make it conditional by using &&.

#!/bin/bash
gcc odd.c -o odd222 && ./odd222

It'd also be good to modify your C code to ensure the printouts are printed immediately. Output is usually line buffered, meaning it's only displayed once you write a full line with a newline \n at the end. You'll want to either print a newline:

printf("enter the no.\n");

Or flush the output explicitly:

printf("enter the no.");
fflush(stdout);

How to execute a shell script in C?

The execl function (like all exec(3) functions and the execve(2) system call) don't return on success. It would return only on failure.

So your first call:

execl ("/usr/bin/chmod", "chmod", "+x", "script.sh", (char *)0);

is very likely to succeed. Then your current program is gone, and your process is running the /usr/bin/chmod program. Once that program finished (in a few milliseconds), your process exits (and your invoking shell gives a new prompt).

Instead of using the /usr/bin/chmod program you should consider using the chmod(2) system call.

The rest of your program is also wrong. You might want to exec the generated script (but then, you need to give its entire path).

You need to understand how to run processes using fork(2), execve(2), waitpid(2) and friend system calls. We cannot explain how to do that (it is too long), but you should read several chapters of the Advanced Linux Programming book (freely downloadable).

Perhaps you should consider embedding an interpreter like Lua or Guile in your real program (so your question looks like some XY problem)

And you might just use system(3) or popen(3) to run some command.... Perhaps using something like FILE* cmd = popen("/bin/sh", "w"); might be enough .... Then you'll write shell commands to cmd and you need to pclose(cmd)

How to run a bash script from C++ program

Use the system function.

system("myfile.sh"); // myfile.sh should be chmod +x

Secure way to run shell script with arguments from C, working example

First Choice: Don't Use system() At All

#include <unistd.h>
#include <errno.h>

main(int argc, char **argv) {
int retval;
execl("/path/to/sctcipt.sh", "/path/to/sctcipt.sh", argv[1], NULL);
_exit(1); /* if we got here, the fork() failed */
}

Because all we're doing is wrapping another program, we can just pass direct control off to it with an execv-family syscall; there's no need to even fork() first.


Second Choice: Export Your Variables Through The Environment

Here, the code passed to system() is a constant you've audited yourself; replacements are performed only after the shell is started, by the shell, after it's already finished with the syntax-parsing phase.

#include <unistd.h>
#include <errno.h>

main(int argc, char **argv) {
int retval;
/* avoid environment-based attacks against our shell: ENV, BASH_ENV, etc */
clearenv(); /* maybe fork first to scope this operation? */
/* Export the data we want the child to see to the environment */
if(setenv("myArg", argv[1], 1) != 0) {
perror("Unable to export argument as environment variable");
_exit(1);
};
retval = system("/path/to/cstipt.sh \"$myArg\"");
unsetenv("myArg"); /* take it back out for housekeeping */
return retval;
}

How to store the output of C program using Bash shell scripting

I made an alternative for a.out, that I can use for testing. is_odd.sh looks for odd umbers:

#!/bin/bash

exitfalse() {
echo $*
echo false
exit 1
}

exittrue()
{
echo $*
echo true
exit 0
}

[ $# -eq 0 ] && exitfalse I wanted a number
[[ $1 =~ [0-9]+ ]] || exitfalse Only numbers please
(( $1 % 2 == 0 )) && exitfalse Even number
exittrue Odd number

Using this verbose script gives a lot garbage

#!/bin/bash
testset() {
for input in john doe 1 2 3 4; do
echo "Input ${input}"
./is_odd.sh "${input}"
done
}

testset

How can you have the same output and only false/true in a file?
Use teeto send output to the screen and to some process that will do the filtering:

testset | tee >(egrep "false|true" > output)

I think above command fits best with your question, I would prefer to see the input strings:

testset | tee >(egrep "Input|false|true" > output)


Related Topics



Leave a reply



Submit