Capturing shell script exit status in c++ [duplicate] - c++

This question already has answers here:
How to get the exit code of program invoked by system call?
(3 answers)
Closed 5 years ago.
I have a requirement of developing a small dependency manager for a Qt based C++ application I am developing. This C++ application will be targeting Linux systems. So this is how it works. I execute a shell script through the system() function. In the shell script I check whether the required packages are installed, if not I exit the shell script with the status of the last executed command. My question is, how do we capture this in C++ and handle it? (I want to capture it so I can inform the user that some of the dependencies are not installed and seek user permission to install them)
C++ code :
system("./myscript.sh");
Shell code :
iwconfig
exit $?
I've tried this aproach earlier on:
in C++ :
int i = system("./myscript.sh");
if(i!=0)
QMessageBox::information(this, tr("test"), tr("program exited with exit code"+i));
But then I get the following error :
The inferior stopped because it received a signal from the operating system. Signal name : SIGSEGV Signal meaning : Segmentation fault
How to get it done??

Prototype of system command is:
int system(const char *command);
and it returns the exit code of the command, that it executed (the shell script in your example). So you have simply use:
int status = system("./myscript.sh");

I have a requirement of developing a small dependency manager for a Qt based C++ application I am developing.
You should consider instead making a proper package for your (or some common) distribution (e.g. some .deb file for Debian or Ubuntu), because package managers do this job (handing dependency management) better than you reasonably could.
The return code of system(3) is actually the status code given by waitpid(2). Read about exit status of bash and shells. So if the last command executed (by /bin/sh -c started by system(3)) crashed with a SIGSEGV (see signal(7)...) you could use WIFSIGNALED then WTERMSIG
I guess that some program run by your ./myscript.sh crashed badly.
You might consider using the shell trap builtin in your script to handle that.

Related

Hiding console command used while using system()? C++ Linux

Well, I will put it plain and simple: I am a C++ pleb. Still trying to learn though.
My question is: is it possible to run a command though the terminal using system() command without letting the command be shown in the console/terminal?
Example:
system("sudo service sshd start") ;
Output: Sudo service sshd start
Where as I want:
system("sudo service sshd start") ;
output: (Blank)
Note: I am on linux.
The system standard library function starts up a subshell and executes the provided string as a command within that subshell. (Note that a subshell is simply a process running a shell interpreter; the particular shell interpreter invoked by system will depend on your system. No terminal emulator is used; at least, not on Unix or Unix-like systems.)
The system function does not reassign any file descriptors before starting the subshell, so the command executes with the current standard input, output and error assignments. Many commands will output to stdout and/or stderr, and those outputs will not be supressed by system.
If you want the command to execute silently, then you can redirect stdout and/or stderr in the command itself:
system("sudo service sshd start >>/dev/null 2>>/dev/null") ;
Of course, that will hide any error messages which might result from the command failing, so you should check the return value of system and provide your own error message (or log the information) if it is not 0.
This really has very little to do with the system call or the fact that you are triggering the subshell from within your own executable. The same command would have the same behaviour if typed directly into a shell.

Why isn't gdb working for me

Background
I am currently trying to build an autonomous drone using ROS on my Rapsberry Pi which is running an Ubuntu MATE 16.04 LTS. Solving the Computer Vision problem of recognising red circles as of now.
Specific Problem
I am constantly getting the error I get in this question. To help me solve this, I have decided to use gdb. However, the command rosrun --prefix 'gdb run --args' zlab_drone vdstab does not seem to be working for me. zlab_drone is the name of the package and vdstab is the name of the executable I am trying to run. Since this is inside a ROS environment, I have grabbed the syntax from here, and used the suggestions in this question.
When I invoke this command, even with tui, I get a SIGSEGV and when I invoke list inside gdb itself, the program does not stay at a particular point and keeps listing a different line till it is out of range. This is quite a weird issue.
I managed to make it work without this issue earlier by using a different command, I reckon. I just cannot remember how I made it work last time.
Well, in the link you mentioned, it states clear that you should use either :
launch-prefix="xterm -e gdb --args" : run your node in a gdb in a separate xterm window, manually type run to start it
or :
launch-prefix="gdb -ex run --args" : run your node in gdb in the same xterm as your launch without having to type run to start it
So, it really looks like you missed an -ex as #ks1322 suggeseted in the comments or just type run to start the debug process.
I found out about this exclusive bug that relates to Raspberry Pi's solely. Basically the solution involves, as quoted by Peter Bennet:
There is a workaround. Start the program, then from another command
prompt or from an ssh remote login, use gdp -p xxxxx where xxxxx is
the process number. This works without crashing. If you need to debug
something that happens before you can get in from another command
prompt, add to the program a command that stops process at the
beginning of main, for example a call to gets, which will wait for you
to press enter before continuing.

system("history") not working

I've run into a snag, I'm trying to implement a linux shell program of sorts with C++ and many of my commands seem to work, however, when I try to get the history(list all recently executed commands) I get an error of "sh: 1: history: not found" the below line is all that runs in the area, what is the issue?
system("history"); //produces the error above ^
If I do
$ history
from the command line it's fine...why is it not fine in C++?
system executes a program using /bin/sh, but history is a bash builtin.
You might look at the contents of ~/.bash_history instead. (Note (by leemes) .bash_history is only updated after closing a previous bash session, as well as it is not updated by executing a command with system.)
Because it's a bash shell builtin not necessarily accessible through /bin/sh -c` (which may be the bourne shell).

shell process creation error in system() command

I have this piece of code in my c++ project:
std::string run_command = "build/executable input.txt";
std::string copy_command = "cp output.txt output_1.txt;";
int status1= system(run_command.c_str());
int status2=system(copy_command.c_str());
It perfectly runs in my pc, but doesn't work in my laptop. Both system calls return -1, meaning that there is a problem in shell process creation. What do you think is the problem?
As reported by manual:
The value returned is -1 on error (e.g., fork(2) failed), and the
return status of the command otherwise. This latter return status is
in the format specified in wait(2). Thus, the exit code of the command
will be WEXITSTATUS(status). In case /bin/sh could not be executed,
the exit status will be that of a command that does exit(127).
So, path should be correct. Try to add some print debug in your scripts.
Maybe you are referring to resources or libraries that in your laptop does not exist.
try using ptrace and print errno (http://man7.org/linux/man-pages/man3/errno.3.html) to find the reason as to why system call failed. This is another resource to steer you on why the system call failed http://bytes.com/topic/c/answers/217348-get-system-error-message
P.S.
I'm not entirely confident in writing c++ systems programs but i build a shell in C and printing errno helps. I definitely recommend using ptrace as well as monitoring whether the OS has enough resource to allocate new processes.

C++ Keep process alive after it kills its parent

I'm working on implementing a self-updater for a daemon on OS X. The update is published as a .pkg file, so what I'm trying to do is as follows:
When the daemon is notified that an update is available, it calls installer via the system() call to install the package. The package contains a newer version of the daemon, a preupgrade script that stops the daemon (launchctl unload /Library/LaunchDaemons/foo.plist), and a postflight script that starts it back up after the new version is installed. The problem I'm having is that the installer process is quitting prematurely. I suspect that it may be because the installer kills its parent process in order to update it, and then gets killed itself instead of continuing as its own orphan process. I've tried the following with no luck:
Postpending the installer command with '&' to run it in the
background
Wrapping the installer command with nohup
The install command completes consistently without error when I run it from the command line, and fails consistently when run from the installer. When called from the installer, I'm piping the output to a file, and sometimes it has nothing, and sometimes it shows the install getting to about 41% completion before output stops. Any ideas on how I can figure out what's happening to the process or make sure it stays alive without its parent?
When you call launchctl unload, it kills the entire process group (unlike a simple kill). You want to move your subprocess into a separate process group. The easiest way is with the C call setsid().
If you're in the middle of a shell script, you should look at the following approaches. I haven't tried these since I was dealing with a C program and could setsid():
Prior to calling the installer, use set -m. This is supposed to turn on monitor mode, which says "Background processes run in a separate process group and a line containing their exit status is printed upon their completion."
Try this sub-interative shell trick: New process group in shell script