I am currently working on a NFC system using the ACR122U reader and not using the constructor drivers which lead to some occasionnal crashes of those drivers.
The problem here is that when it crashes, the whole process isn't crashed, my program keep running but the drivers don't. (No need to say that it makes my code useless)
I am aware of the ways to restart a crashed program but not crashed drivers. I thought of using a watchdog to hard reset the raspberry but needless to say that a reboot isn't the best choice because of the time it takes. ( I am using the very first Raspberry).
So, is there a way to reboot only the driver and more important, detect when it fails ?
I found a solution to my own problem after many hours of research and trials. The solution is actually very simple : just a background running script (my program in my case), and a check using grep, every two seconds :
#!/usr/bin/env bash
command="/your/path/to/your_script"
log="prog.log"
match="error libnfc"
matchnosp="$(echo -e "${match}" | tr -d '[:space:]')"
$command > "$log" 2>&1 &
pid=$!
while sleep 2
do
if fgrep --quiet "$matchnosp" "$log"
then
echo "SOME MESSAGE"
kill $(pidof your_script)
$command > "$log" 2>&1 &
sleep 5
truncate -s 0 $log
echo "SOME OTHER MESSAGE..."
fi
done
This restart the program when some message matching "error libnfc" is found in the log file.
Related
I need to do a buffer overflow for my system security course. Therefore I do have a program(called canary) I need start which asks for a input string (read()).
I need to calculate a canary(random canary built with PID and time) for a successful buffer overflow. I already wrote a program(getcanary) which gets me the right canary. The problem:
I try to start canary in a extra terminal, then get the PID of it, then calculate the program followed by a write to canary's STDIN. The last thing is where I have a Problem.
#!/bin/bash
echo "start canary"
x-terminal-emulator -e ./canary &
sleep 1
PID=$(pgrep canary)
CANARY=$(./getcanary $PID)
How can I write the command to the extra terminal? I already tried several solutions,
echo "cmd" > /proc/$PID/fd/0
is one of it
I also tried
mkfifo fifo
cat > fifo &
./canary < fifo
echo "cmd" > fifo
some other solutions are not allowed by my environment, as the script must run on a clean install of xubuntu, so I can't use screen or tmux
I hope you can help me,
Thank you! :)
PS.: I'm sorry if I misunderstood any of these solutions I tried, I'm not very familiar with shell scripting.
Write to the terminal, not to the running process!
#!/bin/bash
echo "start canary"
x-terminal-emulator -e ./canary &
termpid=$!
sleep 1
xvkbd -window $(xdotool search --sync --pid $termpid) -text "echo Hello world!\n"
I need to run a jar file (datacollector.jar), say having path (/home/vagrant/datatool) on a Linux machine for a fixed interval of time. For example, from 18:00 10-06-2017 to 03:00 11-06-2017 in some future time. After that, the process should be killed.
I want to write a shell script for this which takes two arguments starting and ending time.
The script should also inform if its already running or not, and I should be able to manually stop it before ending time.
I am unable to figure this out after spending some researching online. How can I achieve this?
I come up with a solution in which myshell.sh take 4 arguments
[start_date] [start_time] [end_date] [end_time].
and script code :
#!/bin/bash
JAR_PATH=/home/vagrant/datatool/datacollector.jar
PID_PATH=/tmp/datacollector-id
#calculate wait time to run the jar
wait=$(($(date -d "$1 $2" "+%s")-$(date "+%s")))
wait_mins=$((wait/60))
#calculate time for which jar file should be executed
run_interval=$(($(date -d "$3 $4" "+%s")-$(date -d "$1 $2" "+%s")))
run_interval_mins=$((run_interval/60))
echo "tool will satrt after $wait_mins"
#wait before running jar file
sleep "$wait_mins"m
#run the jar file
nohup java -jar $JAR_PATH /tmp 2>> /dev/null >> /dev/null &
echo $! > $PID_PATH
#wait for jar execution time
sleep "$run_interval_mins"m
#kill the jar process
PID=$(cat $PID_PATH);
echo "tool process killed"
kill $PID;
echo "program terminated"
and I am running the code with command:
$ nohup ./myshell.sh 2017-06-08 20:07:00 2017-06-08 20:10:00 >> scriptoutput.txt 2>> /dev/null &
and scriptoutput.txt contains:
tool will satrt after 3
tool process killed
program terminated
Where I need to improve my code?
Is there any better way to do it?
There are no wonders: considering your post, you are probably not allowed to modify its source code and recompile it. Thus, you need an external thing, some other process what
starts the jar with a JVM
stops it
informs the user about its start and stop.
The simplest way to do that are the
at command (you can start something in the future with it)
cron command (you can periodically can execute commands with it in the background)
and, the shell scripts.
If it is only a single-time execution, the "at" command would be the best.
Learn about the linux shellscripting by googling for "linux shell scripting tutorial". You can have more specific answers about your problem on the http://unix.stackexchange.com .
I'm running Valgrind's Helgrind tool on a program in a script.
Here's the relevant part of the script:
(The only line I wrote is the first one)
sudo valgrind --tool=helgrind ./core-linux.bin --reset PO 2>> ../Test_CFE_SB/valgrindLog.txt &
PID=$!
printf "\n" >> ../Test_CFE_SB/valgrindLog.txt
sleep $sleepTime
#did it crash?
ps ax | grep $PID | grep -vc grep
RESULT=$?
if [ $RESULT -eq 0 ]
then
sudo kill $PID
echo "Process killed by buildscript."
else
echo $name >> crash.log
OS: 32 bit XUbuntu 14.04
The program helgrind is running on, core-linux.bin, does not shut down by it self, like a server. Runs until it gets a kill command.
What happens is that the program shuts down after the kill $PID command but Helgrind keeps going in the background taking about 94% of the CPU according to top. I then have to kill it using kill -9 and valgrindLog.txt only contains the starting message from Valgrind, no report or anything. I have let it run through the night with the same result so it's not that it's just slow.
I ran the exact same script except used --tool=memcheck instead and that runs perfectly well. valgrindLog.txt contains everything it should and all is well there. Same if I use --tool=drd, all good. But helgrind doesn't want to play ball and unfortunately I'm not so familiar with Valgrind that I can figure this out on my own, so far at least.
To see what your application is doing under Valgrind/helgrind,
you can attach using gdb+vgdb and examine if your program advances
or else, where it stays blocked.
If you cannot attach, then it means that Valgrind is running in its own
code, and that might be a valgrind/helgrind bug.
If you have a small reproducer, file a bug in valgrind bugzilla
I am trying to find a way to monitor a process. If the process is not running it should be checked again to make sure it has really crashed. If it has really crashed run a script (start.sh)
I have tried monit with no succes, I have also tried adding this script in crontab: I made it executable with chmod +x monitor.sh
the actual program is called program1
case "$(pidof program | wc -w)" in
0) echo "Restarting program1: $(date)" >> /var/log/program1_log.txt
/home/user/files/start.sh &
;;
1) # all ok
;;
*) echo "Removed double program1: $(date)" >> /var/log/program1_log.txt
kill $(pidof program1 | awk '{print $1}')
;;
esac
The problem is this script does not work, I added it to crontab and set it to run every 2 minutes. If I close the program it won't restart.
Is there any other way to check a process, and run start.sh when it has crashed?
Not to be rude, but have you considered a more obvious solution?
When a shell (e.g. bash or tcsh) starts a subprocess, by default it waits for that subprocess to complete.
So why not have a shell that runs your process in a while(1) loop? Whenever the process terminates, for any reason, legitimate or not, it will automatically restart your process.
I ran into this same problem with mythtv. The backend keeps crashing on me. It's a Heisenbug. Happens like once a month (on average). Very hard to track down. So I just wrote a little script that I run in an xterm.
The, ahh, oninter business means that control-c will terminate the subprocess and not my (parent-process) script. Similarly, the sleep is in there so I can control-c several times to kill the subprocess and then kill the parent-process script while it's sleeping...
Coredumpsize is limited just because I don't want to fill up my disk with corefiles that I cannot use.
#!/bin/tcsh -f
limit coredumpsize 0
while( 1 )
echo "`date`: Running mythtv-backend"
# Now we cannot control-c this (tcsh) process...
onintr -
# This will let /bin/ls directory-sort my logfiles based on day & time.
# It also keeps the logfile names pretty unique.
mythbackend |& tee /....../mythbackend.log.`date "+%Y.%m.%d.%H.%M.%S"`
# Now we can control-c this (tcsh) process.
onintr
echo "`date`: mythtv-backend exited. Sleeping for 30 seconds, then restarting..."
sleep 30
end
p.s. That sleep will also save you in the event your subprocess dies immediately. Otherwise the constant respawning without delay will drive your IO and CPU through the roof, making it difficult to correct the problem.
I am running a script to install Oracle DB 11g with silent option and response file.
I noticed the shell after executing the command
$ /directory_path/runInstaller -silent -responseFile responsefilename
The install session just closes just giving me a log file location.
The installation process is active in the background. But for me no way to no about the progress and what is going on... till the prompt to run root scripts come. What if I close the putty windows etc?
Any way to keep the installer session active till finished ? and show some sort of progress on-screen ?
Any way to keep the installer session active till finished ?
Yes, you can wait for oracle silent install to finish on linux eg in a shell script as follows.
(Below was with oracle 11g release 2 for Redhat Enterprise Linux.)
You can wait for it to finish by doing:
$ /directory_path/runInstaller -silent -responseFile responsefilename |
while read l ;
do
echo "$l" ;
done
(this relies on the fact that even though the java universal installer runs in the background it keeps using stdout, so "read l" keeps succeeding until the background universal installer process exits)
and show some sort of progress on-screen ?
A bit more tricky but we can do it by figuring out the name of the logfile from the output of runInstaller before it exits. The output contains a line like:
Preparing to launch Oracle Universal Installer from /tmp/xxxxOraInstallTTT. ...
... where the TTT is a timestamp which leads us to the correct log file, /opt/oraInventory/logs/installActionsTTT.log.
Something like (I have not tested this because in my install I do not need progress output):
$ /directory_path/runInstaller -silent -responseFile responsefilename |
(
while read l ;
do
echo "$l" &&
if expr "$l" : "Preparing to launch Oracle Universal Installer from " >/dev/null
then
t=$(expr "$1" : ".*OraInstall\([^.]*\)") &&
log="/opt/oraInventory/logs/installActions${t}.log" &&
tail -f "$log" &
tpid=$!
fi
done
if [ -n "$tpid" ]
then
kill $tpid
fi
#[1]
)
... we can also tell if the install succeeded, because the universal installer always puts its exit status into the log via the two lines:
INFO: Exit Status is 0
INFO: Shutdown Oracle Database 11g Release 2 Installer
... so by adding to the above at #[1] ...
exitStatus=$(expr $(grep -B1 "$log" | head -1) : "INFO: Exit Status is\(.*\)") &&
exit $exitStatus
... the above "script" will exit with 0 status only if the oracle instal completes successfully.
(Note that including the space in the status captured by expr just above is deliberate, because bizarrely expr exits with status 1 if the matched substring is literally "0")
It is astounding that oracle would go to so much trouble to "background" the universal installer on linux/unix because:
it is trivial for the customer to generically run a script in the background:
runInstaller x y z &
... or...
setsid runInstaller x y z
it is very difficult (as we can see above) to wait for a "buried" background process to finish, and it cannot be done generically
Oracle would have saved themselves and everyone else lots of effort by just running the universal installer syncronously from runInstaller/.oui.
One useful option I found is -waitforcompletion and -nowait for windows. setup.exe will wait for completion instead of
spawning the java engine and exiting.
But still trying to figure out a way to tail that log file automatically when running the runInstaller.
UPDATE: Finally this is the only solution that worked for me.
LOGFILE=$(echo /path/oraInventory/logs/$(ls -t /path/oraInventory/logs | head -n 1))
./runInstaller -silent -responseFile /path/db.rsp -ignorePrereq
grep -q 'INFO: Shutdown Oracle Database' $LOGFILE
while [[ $? -ne 0 ]] ; do
tail -1 $LOGFILE
grep -q 'INFO: Shutdown Oracle Database' $LOGFILE
done
Instead of tailing the latest log in oraInventory, kept the process active till the last message is written to the log file. Old school but works.
It's been a while since I did an installation, but I don't think you can make it stay in the foreground; it just launches the JVM and that doesn't (AFAIK) produce any console output until the end, and you see that anyway, so it wouldn't help you much.
You should have plenty to look at though, in the logs directory under your oraInventory directory, which is identified in the oraInst.loc file you either created for the installation or already had, and might have specified on the command line. You mentioned it told you where the log file is when it started, so that would seem a good place to start. The installActions log in that directory will give you more detail than you probably want.
If you do close the terminal, the silentInstall and oraInstall logs tell you when the root scripts need to be run, and the latter even gives you the progress as a percentage - though I'm not sure how reliable that is.
Tailing the oraInstall or installActions files is probably the only way you can show some sort of progress on screen. 'Silent' works both ways, I suppose.
You probably want to "tail" the most up to date logs(ls -t would give that) generated under /tmp/OraInstallXXX directory.