I am trying to find the meaning of exit code 36096 from the following system() call to ksh script.
$proc_ret = system("/path/to/shellscript.sh");
$proc_ret returns "36096"
I have checked the output of shellscript.sh, It run fine until the another shell script (status.sh) inside shellscript.sh was invoked.
only the first line of that script was invoked, the rest of the script was not get invoked.
here is the content of status.sh
echo "a" > /tmp/a
echo "complete."
echo "b" >> /tmp/a
cat /path/to/mail.txt | mail -s "subject" email#domain
echo "mail complete."
echo "c" >> /tmp/a
I don't know why the script did not continue after the first line. the exit code of system call made to shellscript.sh looks strange to me.
If anyone know the meaning of 36096 then please let me know.
Note that 36096 is 141 * 256. As the system docs tell you, 141 is the exit status of the program. Note again, that an exit status >128 from a shell often means that the child process was killed due to a signal. That signal is obtained by subtracting 128 from the exit status (i.e. look at the low 7 bits).
So the script got signal 13, which is SIGPIPE - write on a pipe with no reader.
It looks as if the mail program could not be started (got the PATH right? Usually cron jobs have a very minimal PATH and you need to set it in your script with something like PATH=$(getconf PATH).)
Then cat pipes into a non-existing reader, and voila, there's your signal.
BTW, that's a useless use of cat, since mail -s subj recipient < /path/to/mail.txt would avoid an expensive fork and pipe.
Related
I have a perl file (eg:test.pl) which does some DB operations.
While testing, its working fine.
I execute this file as a background process by using the command
perl test.pl &
Its working properly for some days.
But after some days ,the file execution get stopped.
How can I find the reason or view the error?
I checked the log file "/var/log/httpd/error_log", but can't find anything.
I keep the perl file in a server, which runs in Cent OS.
Any one have idea?
There is no 'perl error log'
But you can define a destination for output to be saved to, just run your script like this:
perl test.pl >> /var/log/some-log-file.log 2>&1 &
This will redirect STDOUT (normal shell output) and STDERR (error output) to /var/log/some-log-file.log instead of to the terminal.
You may also wish to use nohup in order to have the script ignore HANGUP (logout) signals, which could be causing your unexpected terminations:
nohup perl test.pl >> /var/log/some-log-file.log 2>&1 &
Obviously, whichever user you run the script as will need to have write access to the log file.
Note that I'm aware that this is probably not the best or most optimal way to do this but I've run into this somewhere before and I'm curious as to the answer.
I have a perl script that is called from an init that runs and occasionally dies. To quickly debug this, I put together a quick wrapper perl script that basically consists of
#$path set from library call.
while(1){
system("$path/command.pl " . join(" ",#ARGV) . " >>/var/log/outlog 2>&1");
sleep 30; #Added this one later. See below...
}
Fire this up from the command line and it runs fine and as expected. command.pl is called and the script basically halts there until the child process dies then goes around again.
However, when called from a start script (actually via start-stop-daemon), the system command returns immediately, leaving command.pl running. Then it goes around for another go. And again and again. (This was not fun without the sleep command.). ps reveals the parent of (the many) command.pl to be 1 rather than the id of the wrapper script (which it is when I run from the command line).
Anyone know what's occurring?
Maybe the command.pl is not being run successfully. Maybe the file doesn't have execute permission (do you need to say perl command.pl?). Maybe you are running the command from a different directory than you thought, and the command.pl file isn't found.
There are at least three things you can check:
standard error output of your command. For now you are swallowing it by saying 2>&1. Remove that part and observe what errors the system command produces.
the return value of system. The command may run and system may still return an exit code, but if system returns 0, you know the command was successful.
Perl's error variable $!. If there was a problem, Perl will set $!, which may or may not be helpful.
To summarize, try:
my $ec = system("command.pl >> /var/log/outlog");
if ($ec != 0) {
warn "exit code was $ec, \$! is $!";
}
Update: if multiple instance of the command keep showing up in your ps output, then it sounds like the program is forking and running itself in the background. If that is indeed what the command is supposed to do, then what you do NOT want to do is run this command in an endless loop.
Perhaps when run from a deamon the "system" command is using a different shell than the one used when you are running as yourself. Maybe the shell used by the daemon does not recognize the >& construct.
Instead of system("..."), try exec("...") function if that works for you.
I'm writing a PowerShell script that uses $error to detect and respond to errors. My problem is that I get different behavior for the $error object depending on how I run the script. If I run it interactively (specifically, from PowerShell ISE), then errors get added to the collection, but if I run the same script from the command line, the same errors occur, but are not added to the collection.
Here's the script (pared down to illustrate the issue):
# export_exception_test.ps1
# show me how many errors before we start
"Count = " + $error.Count
try {
# treat non-terminating errors as terminating errors.
$ErrorActionPreference = "Stop"
# echo the setting to output
$ErrorActionPreference
# use sqlcmd to save the output of stored procedures to text files.
# The first and third call will fail because the output folder does not exist.
# The second call will succeed.
'first call to sqlcmd'
sqlcmd -S myserver\myinstance -E -s `"`t`" -Q "EXEC mydatabase.dbo.FI_Codes" -b -o "B:\Exports_new\FI_Codes.txt"
'second call to sqlcmd'
sqlcmd -S myserver\myinstance -E -s `"`t`" -Q "EXEC mydatabase.dbo.FI_Codes" -b -o "B:\Exports_newt\FI_Codes.txt"
'third call to sqlcmd'
sqlcmd -S myserver\myinstance -E -s `"`t`" -Q "EXEC mydatabase.dbo.FI_Codes" -b -o "B:\Exports_new\FI_Codes.txt"
# and a whole bunch more of these...
# The error count should be two more than when we started.
"Count = " + $error.Count
# And this should be the most recent error message
"Message = " + $error[0].Message
}
catch [Exception]
{
'exception was caught!!!'
"Count in catch clause = " + $error.Count
$_.Exception.Message
# the ultimate goal is to return a non-successful return code when the exports fail
exit 1
}
finally {
# set this back to what it was
$ErrorActionPreference = "Continue"
# primitive trace output
'finally.'
}
When I run this from PowerShell ISE, it behaves as expected. SQLCMD raises a non-terminating error, which is caught and handled. Here's the output:
PS U:\> C:\Users\etmatt\Documents\PowerShellScripts\export_exception_test.ps1
Count = 0
Stop
first call to sqlcmd
exception was caught!!!
Count in catch clause = 1
Sqlcmd: Error: Error occurred while opening or operating on file B:\Exports_new\FI_Codes.txt (Reason: The system cannot find the path specified).
finally.
But when I run it from the command line, as I would if I were to set up a scheduled task, nothing gets added to $error, and no exceptions are raised. Here's the output:
C:\Users\etmatt>powershell.exe -file "C:\Users\etmatt\Documents\PowerShellScripts\export_exception_test.ps1"
Count = 0
Stop
first call to sqlcmd
Sqlcmd: Error: Error occurred while opening or operating on file B:\Exports_new\FI_Codes.txt (Reason: The system cannot find the path specified).
second call to sqlcmd
third call to sqlcmd
Sqlcmd: Error: Error occurred while opening or operating on file B:\Exports_new\FI_Codes.txt (Reason: The system cannot find the path specified).
Count = 0
Message =
finally.
C:\Users\etmatt>
I also get the same results if I run the script file from the powershell command line rather than cmd.exe (which makes sense). For example:
PS C:\> ."C:\Users\etmatt\Documents\PowerShellScripts\export_exception_test.ps1"
I suspect this has something to do with the execution context or maybe something about parser modes that I'm still not quite grokking, or maybe even my profile (although so far I've been running everything from the same PC under the same account). I've seen a lot of examples online that use this basic approach of try/catch with $ErrorActionPreference = "Stop", so it seems like I should be able to make this work.
So my question is essentially: can I make this script work like I think it should? And if not, what am I misunderstanding? How do I catch these sorts of errors? If it helps, I don't need super detailed exception handling for this one, I just need to know when something goes wrong so that my task monitor can alert me. A non-zero return code from powershell.exe would be sufficient.
I'm looking into the use $?, and $LASTEXITCODE, but I'm betting $? will have the same issue as $error, and both only apply to the last statement executed, which is less than ideal since my real script is quite a bit longer than this example.
EDIT:
OK, I've since learned that Windows executables (such as sqlcmd), never add anything to the $error collection, even if they return a non-zero exit code. $error is only used by cmdlets, if I understand correctly. I got my script working through the repeated use of $LASTEXITCODE, although I could have used $? as well, because it recognizes Windows executable exit codes and gets set to false for non-zero values.
To sum up, the behavior of the script when run from the command line is the correct, expected behavior. Still don't know why I got different results from the PowerShell ISE, though.
For me I am calling batch command using cmd /C <command> and I have the similar problem. For non zero return code $? is set correctly but there is no $error object (how would powershell know? so this is ok) and the code behaves similarly in ISE as well as command line execution.
My problem is that in such cases when $ErrorActionPreference = "Stop" it is not throwing exception. Probably because it doesn't have $error object to throw. So now I need to check $? after every call to other script or program which is not neat. They should come up with good solution for such situation (probably by throwing in-built exception saying call to external script/program failed)
I have a perl script (verifyCopy.pl) that uses system() to call a shell script (intercp.sh).
From inside the shell script, I have set up several exit's with specific exit codes and I'd like to be able to do different things based on which exit code is returned.
I've tried using $?, I have tried assigning the value of system("./intercp.sh") to a variable then checking the value of that, but the error message is always 0.
Is this because even though something inside the shell script fails, the actual script succeeds in running?
I tried adding a trap in the shell script (ie trap testexit EXIT and testexit() { exit 222; } but that didn't work either.
$? should catch the exit code from your shell script.
$ cat /tmp/test.sh
#!/bin/sh
exit 2
$ perl -E 'system("/tmp/test.sh"); say $?'
512
Remember that $? is encoded in the traditional manner, so $? >> 8 gives the exit code, $? & 0x7F gives the signal, and $? & 0x80 is true if core was dumped. See perlvar for details.
Your problem may be one of several things: maybe your shell script isn't actually exiting with the exit code (maybe you want set -e); maybe you have a signal handle for SIGCHLD eating the exit code; etc. Try testing with the extremely simple shell script above to see if its a problem in your perl script or your shell script.
Is it possible to detect when a long running process started with shell-command crashes, so it can automatically be restarted? Without manually checking its buffer and restarting by hand.
I wouldn't handle this from Emacs at all. Instead, I'd write a wrapper script around my original long-running process that restarts the process if it dies in a partiular way. For example, if your program dies by getting the SIGABRT signal, the wrapper script might look like this:
#!/bin/bash
while true
do
your-original-command --switch some args
if [ $? -ne 134 ]; then break; fi
echo "Program crashed; restarting"
done
I got the value 134 for the SIGABRT signal by doing this:
perl -e 'kill ABRT => $$'; echo $?
This is all assuming some kind of Unix-y system.