Executing shell script with system() returns 256. What does that mean? - c

I've written a shell script to soft-restart HAProxy (reverse proxy). Executing the script from the shell works. But I want a daemon to execute the script. That doesn't work. system() returns 256. I have no clue what that might mean.
#!/bin/sh
# save previous state
mv /home/haproxy/haproxy.cfg /home/haproxy/haproxy.cfg.old
mv /var/run/haproxy.pid /var/run/haproxy.pid.old
cp /tmp/haproxy.cfg.new /home/haproxy/haproxy.cfg
kill -TTOU $(cat /var/run/haproxy.pid.old)
if haproxy -p /var/run/haproxy.pid -f /home/haproxy/haproxy.cfg; then
kill -USR1 $(cat /var/run/haproxy.pid.old)
rm -f /var/run/haproxy.pid.old
exit 1
else
kill -TTIN $(cat /var/run/haproxy.pid.old)
rm -f /var/run/haproxy.pid
mv /var/run/haproxy.pid.old /var/run/haproxy.pid
mv /home/haproxy/haproxy.cfg /home/haproxy/haproxy.cfg.err
mv /home/haproxy/haproxy.cfg.old /home/haproxy/haproxy.cfg
exit 0
fi
HAProxy is executed with user haproxy. My daemon has it's own user too. Both run with sudo.
Any hints?

According to this and that, Perl's system() returns exit values multiplied by 256. So it's actually exiting with 1. It seems this happens in C too.

Unless system returns -1 its return value is of the same format as the status value from the wait family of system calls (man 2 wait). There are macros to help you interpret this status:
man 3 wait
Lists these macros and what they tell you.

A code of 256 probably means that the system command cannot locate the binary to run it. Remember that it may not be calling bash and that it may not have paths setup. Try again with full paths to the binaries!

I have the same problem when call script that contains `kill' command in a daemon.
The daemon must have closed the stdout, stderr...
Use something like system("scrips.sh > /dev/null") should work.

Related

C: How to kill a process on another machine through SSH?

I am looking to run a program written in C on my machine and have it SSH into another machine to kill a program running on it.
Inside my program, I have attempted:
system("ssh username#machine.com && pkill sleep && exit");
which will cause my terminal to SSH into the remote machine, but it ends there. I have also tried:
execl("ssh","ssh","username#machine.com",NULL);
execl("pkill","pkill","sleep",NULL);
execl("exit","exit",NULL);
but it will not kill my dummy sleep process I have running.
I can't seem to figure out what is wrong with my process.
Your second example won't do what you want as it will execute each execl on the local machine. IE it will
Execute ssh usrname#machine.com
Execute pkill
Execute exit
But, actually, unless you are surrounding these by fork, the first execl if it succeeds in running at all will replace the current process, meaning the second and third ones never get called.
So, let's work out why the first (more hopeful) example doesn't work.
This should do the equivalent of:
/bin/sh -c 'ssh username#machine.com && pkill sleep && exit'
The && exit is superfluous. And you want the pkill to run on the remote machine. Therefore you want something that does:
/bin/sh -c 'ssh username#machine.com pkill sleep'
(note the absence of && so the pkill is run on the remote machine).
That means you want:
system("ssh username#machine.com pkill sleep");
If that doesn't work, check the command starting /bin/sh -c above works. Does ssh ask for a password, for instance? If so, it won't work. You will need to use a public key.
one can always run, over ssh, the command:
kill $(pgrep -o -f 'command optional other stuff')
Get your remote process to handle SIGTERM, where it can do its cleanup's. (including killing any processes its started)
Google 'man pgrep' to see what the -o and -f do. -f is important to correctly target the signal.
the 'pgrep' returns the pid with trailing \n but this does not need to be stripped off before passing it to 'kill'.
Yours
Allan

Shell script for checking if array is empty and restarting program if so

I want to make a shell script that keeps running to check if my two light weight web servers are still running, and restart them if one is not.
I can use the the command pgrep -f thin to get an array (?) of pids of my server called thin.
When this returned array has a count of zero I want to run a command which starts both servers:
cd [path_to_app] && bundle exec thin -C app_config.yml start
pgrep -f thin returns all the pids of the servers that are running. For example:
2354223425
I am new to shell scripting and don't know how to store the results of pgrep-f thin in an array. E.g.,
#!/bin/sh
while true
do
arr=$(pgrep -f thin) # /edited and now THIS WORKS!
#Then I want to check the length of the array and when it is empty run the above
#command, e.g.,
if [ ${#arr[#]} == 0 ]; then
cd [path_to_app] && bundle exec thin -C app_config.yml start
fi
#wait a bit before checking again
sleep 30
done
The first problem I have is that I cannot store the pgrep values in an array, and I am not sure if I can check against zero values. After that I am not sure if there are problems with the other code. I hope someone can help me!
You forgot to execute the command:
arr=($(pgrep -f thin))
[...] when it is empty
If you only check for emptyness, you can directly use the exit status of grep.
-q, --quiet, --silent
Quiet; do not write anything to standard output.
Exit immediately with zero status
if any match is found, even if an error was detected.

Get the output of multiple strace calls in one file

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 can I check for successful execution of last call of system()

Here I want to know the status of the last executed call of system().
I have one script file containing
hciconfig hci0 &> /dev/null
if [ "$?" -ne 0 ]; then
. ./$BT_CLEAN
I want to do same thing in a C Program so I used system() to run the command hciconfig hci0 &>
/dev/null. But how can I know the status of this executed command? In the shell script we used "$?" same here In C: How can I know whether the last command was executed successfully or not?
I used system("hciconfig hci0 &> /dev/null") in C.
To quote man 3 system:
system() returns -1 on error (e.g. fork(2) failed), and the
return status of the command otherwise.

system command hanged in C program, but when I run the command on bash it is successfull

I need to send the arp of a IP to get it's mac address which is configured on different machine. I am arping this ip from a C program by "system(arping -c 3 -i eth0 ) but I see that this is hanged in there.
But if I run the same command from bash "arping -c 3 -i eth0 " it get executed successfully.
I could not understand why system command hanged in this case while the command is successfully completed when run from bash.
Thanks,
Since you said it was hanging you can try:
strace -o my_prog.strace -f ./my_prog
and then kill it after it hangs. Then you can view the strace output file my_prog.strace and try to figure out what went wrong.
You may want to look at the strace man page to see other options that you might like use -- of particular use to me are ones that make it show more data in buffer (and string) input/output.
If it's not really hanging you should check the return value from your call to system( ) and then inspect errno.
edit
Something that I just thought of that could cause a hang would be if arping was actually a link to a setuid root program that did sudo on the real arping and it is waiting on a password to be typed in, but the terminal for that program isn't set correctly.
try system("arping -c 3 -I eth0 ip-addr");
something like:
main()
{
system("arping -c 3 -I eth0 192.168.10.1");
}
Are you using any child process to execute above ?
From Definition of system() :
The system() function shall ignore the SIGINT and SIGQUIT signals, and shall block the SIGCHLD signal, while waiting for the command to terminate. The system() function shall not return until the child process has terminated.
Recommendations:
1.check on the return value of system() & take appropriate decision.
Eg: If return value is zero it means command processor is not available.If a child process cannot be created, or if the termination status for the command language interpreter cannot be obtained, system() shall return -1 and set errno to indicate the error.
2.Use complete shell commands to be executed.
Eg: system("arping -c 3 -I eth0 10.203.198.10");

Resources