I'm having some trouble terminating a shell. I'm starting several filkontroll.sh in the background to regularly check files to see if they have been changed or deleted. It seems to be running fine except that when all the files have been modified, the program won't terminate. It's seems to be stuck in the for-loop somehow.
filkontroll.sh :
#!/bin/bash
clear
declare -i status=1
if [ -f $1 ]
then
status=0
timestamp=$(stat -f "%Sm" -t "%H%M%S" $1)
fi
while [ 0 ]
do
if [ -f $1 ] && [ $status -eq 1 ]
then
echo "Filen $1 ble opprettet."
break
elif [ ! -f $1 ] && [ $status -eq 0 ]
then
echo "Filen $1 ble slettet."
break
elif [ -f $1 ]
then
sistEndret=$(stat -f "%Sm" -t "%H%M%S" $1)
if [ ! $sistEndret -eq $timestamp ]
then
echo "Filen $1 ble endret."
break
fi
fi
sleep $2
done
kontrollflerefiler.sh:
#!/bin/bash
clear
for fil in $#
do
. filkontroll.sh $fil 2 &
done
Related
Trying to figure out how to get working this condition, without using multiple if statement
Check if these files are in the folder, and basically if an integer is major then another, since i use to concat days hours and minute value of time to get two integers, one with current time and the other with schedule time.
FILE1=180.mp4
FILE2=360.mp4
FILE3=720.mp4
FILE4=1080.mp4
FILE5=audio.mp4
TIME=10155
SCHEDULE=20256
if [ test -f "$FILE1" ] && [ test -f "$FILE2" ] && [ test -f "$FILE3" ] && [ test -f "$FILE4" ] && [ test -f "$FILE5" ] && (( TIME > SCHEDULE )) ; then
echo DO EVENT
else
echo DON'T DO EVENT
fi
[ and test are synonyms. You should use one or the other, not both.
Alternative #1:
if test -f "$FILE1" && test -f "$FILE2" && test -f "$FILE3" && test -f "$FILE4" && test -f "$FILE5" && (( TIME > SCHEDULE ))
then
echo "true"
fi
Alternative #2:
if [ -f "$FILE1" ] && [ -f "$FILE2" ] && [ -f "$FILE3" ] && [ -f "$FILE4" ] && [ -f "$FILE5" ] && (( TIME > SCHEDULE ))
then
echo "true"
fi
However, like in any language, you'd be better off using an array:
files=(180.mp4 360.mp4 720.mp4 1080.mp4 audio.mp4)
if (( TIME > SCHEDULE ))
then
for file in "${files[#]}"
do
if ! [ -f "$file" ]
then
echo "Missing $file" >&2
exit 1
fi
done
echo "Do the thing"
fi
It is possible you will get a problem with the echo DON'T DO EVENT. without quoting, you have a single-quote unmatched in that line. The shell will likely issue unexpected EOF while looking for matching `''.
This should really be a comment, but I am still working on the rep points to be able to add comments
I've been handed an assignment which goes as follows;
I should write a program that checks a file and print out if one of the following happens:
File is created
file is modified
file is deleted
I've made a working program ( my noobish way):
bool=true
if [ -e "$1" ]
then
dato=$(date -r "$1" "+%s")
datony=$(date -r "$1" "+%s")
while [ "$bool" = true ]
do
echo "File exists!"
sleep $2
datony=$(date -r "$1" "+%s")
if [ "$dato" -ne "$datony" ]
then
bool=false
echo "File modified!"
fi
if [ ! -e "$1" ]; then
bool=false
echo "File erased"
fi
done
fi
if [ ! -e "$1" ]
then
while [ "$bool" = true ]
do
echo "File does not exist!"
sleep $2
if [ -e "$1" ]
then
bool=false
echo "File created!"
fi
done
fi
The problem now is that i should make a new script that should take multiple files and check their statuses using my existing script. I need som help with how i should use my script to do that.
If you want to continue using $1 for files and $2 for sleep time.
first, put sleep time in a variable
sleepTime=$2
Put all the code you already made in a function (or a program)
checkFile(){
bool=true
if [ -e "$1" ]
then
dato=$(date -r "$1" "+%s")
datony=$(date -r "$1" "+%s")
while [ "$bool" = true ]
do
echo "File exists!"
sleep $2
datony=$(date -r "$1" "+%s")
if [ "$dato" -ne "$datony" ]
then
bool=false
echo "File modified!"
fi
if [ ! -e "$1" ]; then
bool=false
echo "File erased"
fi
done
fi
if [ ! -e "$1" ]
then
while [ "$bool" = true ]
do
echo "File does not exist!"
sleep $2
if [ -e "$1" ]
then
bool=false
echo "File created!"
fi
done
fi
}
create another function to separate the files and call the other function on background.
func_splitFiles(){
while [ ! -z $1 ];
do
checkFile $1 $sleepTime &
shift;
done;
}
In the "main" program you just call the function to split files passing $1
func_splitFiles $1
You should call the program passing files between quotes.
program.sh "file1 file2 file3" 1
I have to find a way to have my script read from one of these three options:
a file argument
standard input
a previously established environment variable
Here's what I currently have:
#!/bin/bash
key=$1
[ $# -ge 1 -a -f "$2" ] && input="$2" || [ -f "$INPUT" ] && input="$INPUT" || input="-"
echo $input
Only the environment variable refuses to work, the rest works fine.
I've tried using the export INPUT="pathnametofile" before but it doesn't make any difference, I end up with the shell asking me to enter info as if I called on cat.
The problem in your script
Your attemp is not working due to the way the shell processes a Lists of Commands:
‘&&’ and ‘||’ have equal precedence.
AND and OR lists are executed with left associativity.
Your sentence:
[ $# -ge 1 -a -f "$2" ] && input="$2" || [ -f "$INPUT" ] && input="$INPUT" || input="-"
does the same as follows:
[ $# -ge 1 -a -f "$2" ] && input="$2"
[ $? -eq 0 ] || [ -f "$INPUT" ]
[ $? -eq 0 ] && input="$INPUT"
[ $? -eq 0 ] || input="-"
Now yo may see why your unexpected behaviour.
A better attempt grouping commands
{ [ $# -ge 1 -a -f "$2" ] && input="$2"; } || { [ -f "$INPUT" ] && input="$INPUT"; } || input="-"
Now, due to precedence, the first group is not needed at all:
[ $# -ge 1 -a -f "$2" ] && input="$2" || { [ -f "$INPUT" ] && input="$INPUT"; } || input="-"
Furthermore, unless you have set the positional parameters by hand, you can remove the first check (after all, if $2 is emtpy, -f "" fails the same).
[ -f "$2" ] && input="$2" || { [ -f "$INPUT" ] && input="$INPUT"; } || input="-"
An alternative with the if conditional construct
if [ -f "$2" ]; then
input=$2
elif [ -f "$INPUT" ]; then
input=$INPUT
fi
echo "${input:=-}"
untested, but you'll probably have better luck with if commands, and test that the variable is not empty:
if [ $# -ge 1 -a -f "$2" ]; then
input="$2"
elif [ -n "$INPUT" -a -f "$INPUT" ]; then
input="$INPUT"
else
input="-"
fi
I am creating a script to check for 3 files in Directory, take the count of rows in them and mail if the rows exist.I have to send only one mail if either of these files have count, I am ending up sending 3 mails.
For Ex. I have these files
process_date.txt
thread_date.txt
child_date.txt
Iam doing something like
$1= process_date.txt
$2= thread_date.txt
$3= child_date.txt
if [ -f $1 ]
then
count1=`wc-l < $1`
if $count1 -ne 0 then mailx abc.com
fi
fi
if [ -f $2 ]
then
count2=`wc-l < $2`
if $count2 -ne 0 then mailx abc.com
fi
fi
if [ -f $3 ]
then
count3=`wc-l < $3`
if $count3 -ne 0 then mailx abc.com
fi
fi
As you stated your question, it seems you only need to check whether at least one of the files is non-empty: you don't need to count the number of rows. In Bash, you may use the [[ -s file ]] test to exactly test whether file exists and is non-empty. So you can do:
#!/bin/bash
if [[ -s $1 ]] || [[ -s $2 ]] || [[ -s $3 ]]; then
mailx abc.com
fi
More generally, you can have the mail sent if at least one of the files given as arguments exists and is non-empty:
#!/bin/bash
for file; do
if [[ -s $file ]]; then
mailx abc.com
break
fi
done
You'll call this as
scriptname process_date.txt thread_date.txt child_date.txt
You can wrap your script in a function and use return command after every mailx, like this:
send_one_mail() {
if [ -f "$1" ]
then
count1=$(wc -l < "$1")
if [ $count1 -ne 0 ]
then
mailx abc.com
return
fi
fi
# etc. for other conditions
}
send_one_mail process_date.txt thread_date.txt child_date.txt
Try this:
if [ -f $1 ]
then
count1=`wc -l < $1`
fi
if [ -f $2 ]
then
count2=`wc -l < $2`
fi
if [ -f $3 ]
then
count3=`wc -l < $3`
fi
if [ $count1 -ne 0 -o $count2 -ne 0 -o $count3 -ne 0 ]
then
mailx abc.com
fi
I am trying to do a simple condition check, but it doesn't seem to work.
If $# is equal to 0 or is greater than 1 then say hello.
I have tried the following syntax with no success:
if [ "$#" == 0 -o "$#" > 1 ] ; then
echo "hello"
fi
if [ "$#" == 0 ] || [ "$#" > 1 ] ; then
echo "hello"
fi
This should work:
#!/bin/bash
if [ "$#" -eq 0 ] || [ "$#" -gt 1 ] ; then
echo "hello"
fi
I'm not sure if this is different in other shells but if you wish to use <, >, you need to put them inside double parenthesis like so:
if (("$#" > 1))
...
This code works for me:
#!/bin/sh
argc=$#
echo $argc
if [ $argc -eq 0 -o $argc -eq 1 ]; then
echo "foo"
else
echo "bar"
fi
I don't think sh supports "==". Use "=" to compare strings and -eq to compare ints.
man test
for more details.
If you are using the bash exit code status $? as variable, it's better to do this:
if [ $? -eq 4 -o $? -eq 8 ] ; then
echo "..."
fi
Because if you do:
if [ $? -eq 4 ] || [ $? -eq 8 ] ; then
The left part of the OR alters the $? variable, so the right part of the OR doesn't have the original $? value.
Sometimes you need to use double brackets, otherwise you get an error like too many arguments
if [[ $OUTMERGE == *"fatal"* ]] || [[ $OUTMERGE == *"Aborting"* ]]
then
fi
If a bash script
If [[ $input -gt number || $input -lt number ]]
then
echo .........
else
echo .........
fi
exit
have you tried something like this:
if [ $# -eq 0 ] || [ $# -gt 1 ]
then
echo "$#"
fi
From Bash Reference Manual → 3.4.2 Special Parameters
#
($#) Expands to the number of positional parameters in decimal.
Therefore, $# will always be either 0 or a bigger integer.
So if you want to do something whenever $# is either 0 or bigger than 1, you just have to check if $# is or is not 1:
[ $# -eq 1 ] && echo "1 positional param" || echo "0 or more than 1"
This uses the syntax:
[ condition ] && {things if true} || {things if false}
And in Bash
line1=`tail -3 /opt/Scripts/wowzaDataSync.log | grep "AmazonHttpClient" | head -1`
vpid=`ps -ef| grep wowzaDataSync | grep -v grep | awk '{print $2}'`
echo "-------->"${line1}
if [ -z $line1 ] && [ ! -z $vpid ]
then
echo `date --date "NOW" +%Y-%m-%d` `date --date "NOW" +%H:%M:%S` ::
"Process Is Working Fine"
else
echo `date --date "NOW" +%Y-%m-%d` `date --date "NOW" +%H:%M:%S` ::
"Prcess Hanging Due To Exception With PID :"${pid}
fi
OR in Bash
line1=`tail -3 /opt/Scripts/wowzaDataSync.log | grep "AmazonHttpClient" | head -1`
vpid=`ps -ef| grep wowzaDataSync | grep -v grep | awk '{print $2}'`
echo "-------->"${line1}
if [ -z $line1 ] || [ ! -z $vpid ]
then
echo `date --date "NOW" +%Y-%m-%d` `date --date "NOW" +%H:%M:%S` ::
"Process Is Working Fine"
else
echo `date --date "NOW" +%Y-%m-%d` `date --date "NOW" +%H:%M:%S` ::
"Prcess Hanging Due To Exception With PID :"${pid}
fi