Performing a command after while loop ended - bash

I'm trying to find a way to use the while loop to check for a certain condition, and if this condition is met, another command will be executed.
For example:
while [ -z "$(ls -A test-dir)" ];
do
echo "directory is empty, checking again in 5 seconds"
sleep 5
done
This loop will end once the directory will have any files inside, I'm trying to find a proper way to execute another command at the end when the loop completed.

Figured out that I need to simply add the last command after the while:
while [ -z "$(ls -A test-dir)" ];
do
sleep 2
echo "sleeping 2 seconds"
done
echo "reached the end"
The last command will be executed only after the loop is done.

Related

How to display long script logs to one liner?

Lets Say I have multiple scripts which need to invoke sequentially for the job.
These scripts has long and lengthy output this is my bash script,
How to avoid that but still can understand that the process is running.
Here is an example,
#!/bin/bash
echo "Script to prepare Final BUILD"
rm -vf module1.out
module1_build_script.sh #FIXME: This scripts outputs 10000 lines
#module1_build_script.sh &> /dev/null #Not interested as this makes difficult if the process hangs or running.
if [ ! -f ./out/module1.out ];then
echo "Module 1 build failed"
exit 1
fi
.
.
.
rm -vf module1.out
module4_build_script.sh # This scripts outputs 5000 lines
if [ ! -f ./out/module4.out ];then
echo "Module 4 build failed"
exit 4
fi
Now I am expecting some code gives me effect like below output as one liner without scroll
example: module1_build_script.sh | "magical code here" #FIXME:
Like below output
user#bash#./myscript
#-------content of myscript ---------------
#!/bin/bash
while (( i < 10))
do
echo -en "\r Process is running...$i"
sleep 0.5
((i++))
done
#------------------------------------------

Bash script if else execute once cronjob every minute

I have a bash script in crontab that runs every minute.
In this bash script i have a sql query which goes and check for the number
If the number is greater than predefined number then I want to move files and replace files.
This works absolutely fine, the problem is that since this script runs every minute via crontab, when the script runs next time it overwrites the file.
Is there any logic that I can put that this code is only run once but let the cron run every minute.
here is the code
#!/bin/bash
count=`mysql -B -u root -ppassword -e 'select count(*) from column' table | tail -n +2`
allowed="500"
if [ "$count" -ge "$allowed" ]
then
mv /netboot/var/www/html /usr/html/
mv /netboot/var/www/back /netboot/var/www/html
echo "Not Allowed - Disable Code goes here"
else
echo "all is good for now $count"
fi
exit 0
Your help is appreciated.
I have managed to fix this by creating another if statement within the parent if.
See below.
#!/bin/bash
count=`mysql -B -u root -ppassword -e 'select count(*) from column' table | tail -n +2`
allowed="500"
if [ "$count" -ge "$allowed" ]
then
if
html folder exists in /usr/
then
mv /netboot/var/www/html /usr/html/
mv /netboot/var/www/back /netboot/var/www/html
else
echo " "
fi
echo "Not Allowed - Disable Code goes here"
else
echo "all is good for now $count"
fi
exit 0

Stop Bash Script if Hive Fails

I have a bash script that loops through a folder and processes all *.hql files. Sometimes one of the hive script fails (syntax, resource constraint, etc), instead of the script failing it will continue onto the next .hql file.
Anyway I can stop the bash from processing the remaining? Below is my sample bash:
for i in `ls ${layer}/*.hql`; do
echo "Processing $i ..."
hive ${hiveconf_all} -hiveconf DATE=${date} -f ${i} &
if [ $j -le 5 ]; then
j=$(( j+1 ))
else
wait
j=0
fi
done
I would check the process completion state of the previous command and invoke the exit command to come out the loop
(( $? == 0 )) && exit 1
Introduce the above line after the hive command and should do the trick.
add
set -e
to the top of your script
Use this template for running parallel processes and wait for their completion. Add your date, layer, hiveconf_all and other variables:
#!/bin/bash
set -e
#Run parallel processes and write their logs
log_dir=/tmp/my_script_logs
for i in `ls ${layer}/*.hql`; do
echo "Processing $i ..."
#Run hive in parallel and redirect to the log file
hive ${hiveconf_all} -hiveconf DATE=${date} -f ${i} 2>&1 | tee "log_dir/${i}".log &
done
#Now wait for all processes to complete
FAILED=0
for job in `jobs -p`
do
echo "job=$job"
wait $job || let "FAILED+=1"
done
if [ "$FAILED" != "0" ]; then
echo "Execution FAILED! ($FAILED)"
#Do something here, log or send message, etc
exit 1
fi
#All processes are completed successfully!
#Do something here
echo "Done successfully"
Then you will be able to inspect each process log individually.

How to proceed in the script if file exists ?

how to proceed in the script if file exists?
#!/bin/bash
echo "Start"
# waiting to be exist file
echo "file already exists, continuing"
Do a while if a sleep X, so that it will check the existence of the file every X seconds.
When the file will exist, the while will finish and you will continue with the echo "file already exists, continuining".
#!/bin/bash
echo "Start"
### waiting to be exist file
while [ ! -f "/your/file" ]; # true if /your/file does not exist
do
sleep 1
done
echo "file already exists, continuing"
And goes instead of checking the file existence check if the script
has already completed the background?
Based on the code you posted, I did some changes to make it work completely:
#!/bin/bash
(
sleep 5
) &
PID=$!
echo "the pid is $PID"
while [ ! -z "$(ps -ef | awk -v p=$PID '$2==p')" ]
do
echo "still running"
sleep 1
done
echo "done"
There are OS-specific ways to perform blocking waits on the file system. Linux uses inotify (I forget the BSD equivalent). After installing inotify-tools, you can write code similar to
#!/bin/bash
echo "Start"
inotifywait -e create $FILE & wait_pid=$!
if [[ -f $FILE ]]; then
kill $wait_pid
else
wait $wait_pid
fi
echo "file exists, continuing"
The call to inotifywait does not exit until it receives notification from the operating system that $FILE has been created.
The reason for not simply calling inotifywait and letting it block is that there is a race condition: the file might not exist when you test for it, but it could be created before you can start watching for the creation event. To fix that, we start a background process that waits for the file to be created, then check if it exists. If it does, we can kill inotifywait and proceed. If it does not, inotifywait is already watching for it, so we are guaranteed to see it be created, so we simply wait on the process to complete.
To fedorqui: Is it so good? There is a problem?
#!/bin/bash
(
..
my code
..
) &
PID=$BASHPID or PID=$$
while [ ! ps -ef | grep $PID ]
do
sleep 0
done
Thank you

simple script to check if a webpage has been updated

There is some information that I am waiting for on a website. I do not wish to check it every hour. I want a script that will do this for me and notify me if this website has been updated with the keyword that I am looking for.
Here is a basic bash script for checking if the webpage www.nba.com contains the keyword Basketball. The script will output www.nba.com updated! if the keyword is found, if the keyword isn't found the script waits 10 minutes and checks again.
#!/bin/bash
while [ 1 ];
do
count=`curl -s "www.nba.com" | grep -c "Basketball"`
if [ "$count" != "0" ]
then
echo "www.nba.com updated!"
exit 0
fi
sleep 600
done
We don't want the site or the keyword hard-coded into the script, we can make these arguments with the following changes.
#!/bin/bash
while [ 1 ];
do
count=`curl -s "$1" | grep -c "$2"`
if [ "$count" != "0" ]
then
echo "$1 updated!"
exit 0
fi
sleep 600
done
Now to run the script we would type ./testscript.sh www.nba.com Basketball. We could change the echo command to have the script send an email or any other preferred way of notification. Note we should check that arguments are valid.
go and configure a google alert..
You can also crawl the website and search for the keyword you are interested in.

Resources