Kind of suck at bash here. Looking for help. I'm trying to write a script that takes an int argument, and sleeps for 10 * argument seconds, then displays the current date and time.
I also want an infinite loop, and a message to echo when it is ctrl c'd out of.
Here's what I've got so far:
#!/bin/bash
trap "echo I'm done here && exit" INT
time=10*$1
now="$(date)"
while :
do
sleep "$time"
echo ""
echo "Current date and time: $now"
done
#!/bin/bash
trap "echo \"I'm done here\" && exit" INT
if [[ ! $1 ]]; then # check #triplee comment below
echo >&2 "Missing arg 1"
exit 1
fi
while true; do
sleep $((10 * $1))
echo "Current date and time: $(date)"
done
Check http://mywiki.wooledge.org/ArithmeticExpression
And check what #JNevill said in comments upper
Related
For example, in the below script startover starts back from the top:
##########################################################################
## CHECK TIME
##########################################################################
time=$(date +%k%M)
if [[ "$time" -ge 1800 ]] && [[ "$time" -le 2200 ]];then
echo "Not a good time to transcode video!" && exit 0
else
echo "Excellent time to transcode video!" && echo "Lets get started!"
fi
##########################################################################
## CHECK TIME
##########################################################################
startover
Also keeping in mind exit 0 should be able to stop the script.
You could "recurse" using the following line:
exec bash "$0" "$#"
Since $0 is the path to the current script, this line starts the script without creating a new process, meaning you don't need to worry about too many restarts overflowing the process table on your machine.
Put it in a while loop. I'd also suggest you add a "sleep" so that you're not racing your machine's CPU as fast as it will go:
while true; do
##########################################################################
## CHECK TIME
##########################################################################
time=$(date +%k%M)
if [[ "$time" -ge 1800 ]] && [[ "$time" -le 2200 ]]; then
echo "Not a good time to transcode video!" && exit 0
else
echo "Excellent time to transcode video!" && echo "Lets get started!"
fi
##########################################################################
## CHECK TIME
##########################################################################
for i in {1..5}; do
echo $i
sleep 1
done
done
DO NOT USE WHILE LOOP at the start of the script since the condition below will exit the script and break the loop.
echo "Not a good time to transcode video!" && exit 0
You can try trapping the exit signal so that when the script exits it restarts
##########################################################################
## CHECK TIME
############bash##############################################################
trap '<path to script> ' EXIT
time=$(date +%k%M)
if [[ "$time" -ge 1800 ]] && [[ "$time" -le 2200 ]];then
echo "Not a good time to transcode video!" && exit 0
sleep 1;
else
echo "Excellent time to transcode video!" && echo "Lets get started!"
sleep 1;
fi
##########################################################################
## CHECK TIME
##########################################################################
echo 1
echo 2
echo 3
echo 4
echo 5
startover
Note: I add a sleep of 1 second because this will give you the time to see message. trap the exit signal and re-running the script is acting like a while loop. I am also assuming that these codes are in a script.
How about enclosing the entire script in a while loop? For example,
while :
do
script
done
You may want to add a condition to break out of the loop.
This is not good practice, but what you asked for.
Put this at the end of your script. "$( cd "$( dirname "$0" )" && pwd )/$(basename $0)"
Here is an example script, simple.sh, that launches a background process, sends it a signal, and verifies that the signal was handled:
#!/bin/bash
function on_signal() {
echo "1 caught $1, exiting!"
exit 0
}
function my_sleep {
trap "on_signal $1" $1
echo "1 mypid=$$"
echo "1 mybashpid=$BASHPID"
echo "1 start sleep"
for i in {1..10};
do
echo "1 sleeping $i"
sleep 1
done
echo "1 failed"
exit 1
}
signal=SIGINT
if [[ ! -z $1 ]]; then
signal=$1
fi
my_sleep $signal &
sleeppid=$!
echo ">>> sleeppid=$sleeppid"
sleep 1 # to give script time to run trap
echo ">>> sending $signal"
kill -$signal $sleeppid
for i in 0.25 0.5 1 2; do
echo ">>> trying $i"
if kill -0 $sleeppid 2> /dev/null; then
echo ">>> still running..."
sleep $i
else
echo ">> success"
exit 0
fi
done
echo "Failure"
exit 1
Now, when I run ./simple.sh, it works fine. When I run it in the background, ./simple.sh &, it works fine as well. However, when I add a wrapper, w1.sh, that runs simple.sh in the background, it suddenly stops working:
#!/bin/bash
./simple1.sh $1 &
Now ./w1.sh results in Failure. Why?
I have read https://www.cons.org/cracauer/sigint.html, and it was very informative, but I still cannot understand how the child process itself can behave differently depending on the context it was called in.
Note: I know a "workaround" to get it to behave the way I want to (w1.sh should call (./simple.sh $1) & in a subshell), but I want to understand what's going on there, and why the workaround works.
Thank you!
How to avoid printing an error in Bash? I want to do something like this. If the user enters a wrong argument (like a "." for example), it will just exit the program rather than displaying the error on the terminal. (I've not posted the whole code here... That's a bit long).
if [ -n "$1" ]; then
sleep_time=$1
# it doesn't work, and displays the error on the screen
sleep $sleep_time > /dev/null
if [ "$?" -eq 0 ]; then
measurement $sleep_time
else
exit
fi
# if invalid arguments passed, take the refreshing interval from the user
else
echo "Proper Usage: $0 refresh_interval(in seconds)"
read -p "Please Provide the Update Time: " sleep_time
sleep $sleep_time > /dev/null
if [ "$?" -eq 0 ]; then
measurement $sleep_time
else
exit
fi
fi
2>/dev/null will discard any errors. Your code can be simplified like this:
#!/usr/bin/env bash
if [[ $# -eq 0 ]]; then
echo "Usage: $0 refresh_interval (in seconds)"
read -p "Please provide time: " sleep_time
else
sleep_time=$1
fi
sleep "$sleep_time" 2>/dev/null || { echo "Wrong time" >&2; exit 1; }
# everything OK - do stuff here
# ...
I'm trying to make a script to see if the process chromium is running.
The script should check every 10 seconds if the process is running and it must end when it finds it 10 times.
Here is my code.
#!/bin/bash
count=0
while true; do
sleep 10s
isthere=`$(top) | grep -w chromium`
if [ $isthere -ne 0 ]; then
count=$((count+1))
fi
if [ $count -eq 10 ]; then
echo "You found the process 10 times"
exit 50
fi
done
I'm having no output whatsoever. I don't know if I'm using the command top properly.
Yep, your usage of top command is incorrect. You try to invoke it from the shell script and it hangs as a result.
You should use top command with some specific options. I suggest you use it with -b option which corresponds to the "batch" mode and -n options which is for the number of iterations top produces its output. For more information check man top.
Also the test for isthere variable should be amended (we check it for non-emptyness).
The resulting script which works is something like this:
#!/bin/bash
count=0
while true; do
sleep 10s
isthere=`top -b -n 1 | grep -w chromium`
if [ -n $isthere ]; then
count=$((count+1))
fi
if [ $count -eq 10 ]; then
echo "You found the process 10 times"
exit 50
fi
done
Please use pgrep.
$ if pgrep ksh >/dev/null; then echo "ksh is running"; fi
ksh is running
In a loop:
i=0
while (( i < 10 )); do
if pgrep ksh >/dev/null; then
(( ++i ))
fi
sleep 10
done
Substitute ksh with the tool of your choice.
I am using exit 1 to stop a shell script execution when error occured.
Shell Script
test() {
mod=$(($1 % 10))
if [ "$mod" = "0" ]
then
echo "$i";
exit 1;
fi
}
for i in `seq 100`
do
val=`test "$i"`
echo "$val"
done
echo "It's still running"
Why it's not working?. How can I stop the shell script execution?
The shell that exit is exiting is the one started by the command substitution, not the shell that starts the command substitution.
Try this:
for i in `seq 100`
do
val=`test "$i"` || exit
echo "$val"
done
echo "It's still running"
You need to explicitly check the exit code of the command substitution (which is passed through by the variable assignment) and call exit again if it is non-zero.
Incidentally, you probably want to use return in a function rather than exit. Let the function caller decide what to do, unless the error is so severe that there is no logical alternative to exiting the shell:
test () {
if (( $1 % 10 == 0 )); then
echo "$i"
return 1
fi
}
The exit command terminates only the (sub)shell in which it is executed.
If you want to terminate the entire script, you have to check the exit status
($?) of the function and react accordingly:
#!/bin/bash
test() {
mod=$(($1 % 10))
if [ "$mod" -eq "0" ]
then
echo "$i";
exit 1;
fi
}
for i in `seq 100`
do
val=`test "$i"`
if [[ $? -eq 1 ]]
then
exit 1;
fi
echo "$val"
done
echo "It's still running"