How do I pause my shell script for a second before continuing? - bash

I have only found how to wait for user input. However, I only want to pause so that my while true doesn't crash my computer.
I tried pause(1), but it says -bash: syntax error near unexpected token '1'. How can it be done?

Use the sleep command.
Example:
sleep .5 # Waits 0.5 second.
sleep 5 # Waits 5 seconds.
sleep 5s # Waits 5 seconds.
sleep 5m # Waits 5 minutes.
sleep 5h # Waits 5 hours.
sleep 5d # Waits 5 days.
One can also employ decimals when specifying a time unit; e.g. sleep 1.5s

And what about:
read -p "Press enter to continue"

In Python (question was originally tagged Python) you need to import the time module
import time
time.sleep(1)
or
from time import sleep
sleep(1)
For shell script is is just
sleep 1
Which executes the sleep command. eg. /bin/sleep

Run multiple sleeps and commands
sleep 5 && cd /var/www/html && git pull && sleep 3 && cd ..
This will wait for 5 seconds before executing the first script, then will sleep again for 3 seconds before it changes directory again.

I realize that I'm a bit late with this, but you can also call sleep and pass the disired time in. For example, If I wanted to wait for 3 seconds I can do:
/bin/sleep 3
4 seconds would look like this:
/bin/sleep 4

On Mac OSX, sleep does not take minutes/etc, only seconds. So for two minutes,
sleep 120

Within the script you can add the following in between the actions you would like the pause. This will pause the routine for 5 seconds.
read -p "Pause Time 5 seconds" -t 5
read -p "Continuing in 5 Seconds...." -t 5
echo "Continuing ...."

read -r -p "Wait 5 seconds or press any key to continue immediately" -t 5 -n 1 -s
To continue when you press any one button
for more info check read manpage ref 1, ref 2

You can make it wait using $RANDOM, a default random number generator. In the below I am using 240 seconds. Hope that helps #
> WAIT_FOR_SECONDS=`/usr/bin/expr $RANDOM % 240` /bin/sleep
> $WAIT_FOR_SECONDS

use trap to pause and check command line (in color using tput) before running it
trap 'tput setaf 1;tput bold;echo $BASH_COMMAND;read;tput init' DEBUG
press any key to continue
use with set -x to debug command line

Related

How to run bash commad for n mins, sleep m seconds, and resume it again for n mins, and loop until it is finished?

I would like to implement the following in a bash script:
Run my command
Pause after n mins.
Sleep for m mins.
Check if the command didn't finish, if so, continue for n mins.
Go to no. 2 until it finishes.
This is what I tried so far:
n=n # run command for n mins
my command &
PID=$! # background process id
at now + $n minutes <<<"kill -TSTP $PID" # if time is 4 mins, pause
# if command is not done continue
while [ps -p $PID > /dev/null]
do
echo "$PID did not finish" # sleep for 60 secs
sleep m
kill -CONT $PID
at now + $n minutes <<<"kill -TSTP $PID" # if time is n mins, pause
done
The code is meant to compile a package, and it should be compiled on a remote machine where a CPU limit is implement. Additionally, I'm not an admin there. However, it still fires CPU time limit exceeded error

Bash wait terminates immediately?

I want to play a sound after a command finishes, but only if the command took more than a second.
I have this code (copied from https://stackoverflow.com/a/11056286/1757964 and modified slightly):
( $COMMAND ) & PID=$!
( sleep 1; wait -f $PID 2>/dev/null; paplay "$SOUND" ) 2>/dev/null & WATCH=$!
wait -f $PID 2>/dev/null && pkill -HUP -P $WATCH
The "wait" on the second line seems to terminate immediately, though. I tried the -f flag but the behavior didn't change. How can I make the "wait" actually wait?
The problem is that you're running wait in a subshell. A shell can only wait for its own children, but the process you're trying to wait for is a sibling of the subshell, not a child.
There's no need to use wait for this. The question you copied the code from is for killing a process if it takes more than N seconds, not for telling how long a command took.
You can use the SECONDS variable to tell if it took more than a second. This variable contains the number of seconds since the shell started, so just check if it has increased.
start=$SECONDS
$COMMAND
if (($SECONDS > $start))
then
paplay "$SOUND"
fi
I'd probably want to streamline this to capture the data (in # of seconds since epoch) and then compare the difference (and if > 1 second then play sound), eg:
prgstart=$(date '+%s') # grab current time in terms of # of seconds since epoch
$COMMAND # run command in foreground => no need for sleep/wait/etc; once it completes ...
prgend=$(date '+$s') # grab current time in terms of # of seconds since epoch
if [[ $(( ${prgend} - ${prgstart} )) -gt 1 ]]
then
paplay "$SOUND"
fi

Start background process from shellscript then bring back to foreground later

I'm trying to make a shell script that does the following:
Start program x
While x is running execute some commands, for example:
echo "blabla" >> ~/blabla.txt
After the execution of those commands program x should be running in the foreground, so that it can take user input.
So far I have:
~/x &
echo "blabla" >> ~/blabla.txt
However, I don't know how to move x back to the foreground. This is all called from a shell script so I don't know the job number of x to move to the foreground.
Note: everything has to be automated, no user interaction with the shell script should be needed.
Any suggestions are welcome :)
Although absolutely don't understand why someone may need such script, and I'm sure than exists more elegant and more better/correct solution - but ok - the next demostrating how:
The script what going to background (named as bgg)
#!/bin/bash
for i in $(seq 10)
do
echo "bg: $i"
sleep 1
done
read -p 'BGG enter something:' -r data
echo "$0 got: $data"
the main script (main.sh)
set -m #this is important
echo "Sending script bgg to background - will cycle 10 secs"
./bgg & 2>/dev/null
echo "Some commands"
date
read -r -p 'main.sh - enter something:' fgdata
echo "Main.sh got: ==$fgdata=="
jnum=$(jobs -l | grep " $! " | sed 's/\[\(.*\)\].*/\1/')
echo "Backgroung job number: $jnum"
echo "Now sleeping 3 sec"
sleep 3
echo "Bringing $jnum to foreground - wait until the BG job will read"
fg $jnum
run the ./main.sh - and the result will be something like
Sending bgg to background - will cycle 10 secs
Some commands
Mon Mar 3 00:04:57 CET 2014
main.sh - enter something:bg: 1
bg: 2
bg: 3
bg: 4
bg: 5
qqbg: 6
qqqqq
Main.sh got: ==qqqqqqq==
Backgroung job number: 1
Now sleeping 3 sec
bg: 7
bg: 8
bg: 9
Bringing 1 to foreground - wait until the BG job will read
./bgg
bg: 10
BGG enter something:wwwwwww
./bgg got: wwwwwww
You can use fg to bring the last background process to foreground

Why does `timeout` not work with pipes?

The following command line call of timeout (which makes no sense, just for testing reason) does not work as expected. It waits 10 seconds and does not stop the command from working after 3 seconds. Why ?
timeout 3 ls | sleep 10
What your command is doing is running timeout 3 ls and piping its output to sleep 10. The sleep command is therefore not under the control of timeout and will always sleep for 10s.
Something like this would give the desired effect.
timeout 3 bash -c "ls | sleep 10"
The 'ls' command shouldn't be taking 3 seconds to run. What I think is happening is you are saying (1) timeout on ls after 3 seconds (again this isn't happening since ls shouldn't take anywhere near 3 seconds to run), then (2) pipe the results into sleep 10 which does not need further arguments than the number you are giving it. Thus ls happens, timeout doesn't matter, and bash sleeps for 10 seconds.
The only way I know how to get the effect you're after, is to put the piped commands into a separate file:
cat > script
ls | sleep 10
^D
timeout 3 sh script
It is enough to set the timeout on the last command of the pipeline:
# Exits after 3 seconds with code 124
ls | timeout 3 sleep 10
# Exits after 1 second with code 0
ls | timeout 3 sleep 1

Script repeat itself after X minutes

I have a bash script in Ubuntu, I want it to run every 10 minutes for example after it's done. How can I do this? Thanks!
You can check watch.
From the man pages of watch the description says watch - execute a program periodically, showing output fullscreen, you can try watch -n 600 my_script.sh which will execute myscript.sh every 600 seconds i.e. 10 minutes. watch shows the output to full screen, you can redirect it to say /dev/null in case you are not interested in the output to the screen.
Hope this helps!
Cronjobs is what you need.
My blog post:- http://linux-junky.blogspot.com/2010/10/guide-to-add-cronjob-simplified.html
Or you can also use sleep 600 in your script.
You can use at to reschedule the script from within the script. At the end of the script put:
at now + 10 minutes << END
"$0" "$#"
END
Or with crontab -e, or another option, to check the date. for example, if you want to do something every 10 minutes, you can write:
if [ $((`date +%M`%10)) -eq 0 ] && [ `date +%S` -lt 10 ]; then
#your code
fi

Resources