Exit script if a file doesn't exist - linux

I try to calculate time differences between two log, but when there is no log in logfile, unix takes own birthdate 1970. My script is below. I want to exit from script if there is no log in logfile.
#!/bin/bash
a=`tail -n 1 /var/log/nginx/error.log | awk -F" " '{print $1" "$2}' | cut -c12-20`
f=`date '+%Y-%m-%d %H:%M:%S' | cut -c12-19`
VAR1=$(date -u --date="$a sec UTC" +%s)
VAR2=$(date -u --date="$f sec UTC" +%s)
DIFF2=$(( $VAR2 - $VAR1 ))
if [ $DIFF2 -lt 59 ]; then
echo "ok"
else
echo "nok"
fi

I guess that with if there is no log in logfile, you mean that the logfile either does not exist or is empty. You can do this in bash with
logfile=/var/log/nginx/error.log
[[ -f $logfile && -s $logfile ]] || exit 1
-f tests that it is a plain file, and -s tests that it is not empty.

You can check fr the existence of a file using:
if [ ! -f '/var/log/ngnix/error.log' ]
then
exit
fi

Just check if file doesn't exist or is empty and exit code
LOG_FILE="/var/log/nginx/error.log"
[ ! -s $LOG_FILE -o ! -f $LOG_FILE ] && exit $?

Related

Download only part of a youtube video precise by the millisecond

I used this bash script here to download only short parts of long yt videos:
#!/bin/bash
#taken from https://unix.stackexchange.com/a/388148/48971
if [ $# -lt 4 ]; then
echo "Usage: $0 <youtube's URL> <HH:mm:ss.milisecs from time> <HH:mm:ss.milisecs to time> <output_file_name>"
echo "e.g.:"
echo "$0 https://www.youtube.com/watch?v=T1n5gXIPyws 00:00:25 00:00:42 intro.mp4"
exit 1
fi
echo "processing..."
from=$(date "+%s" -d "UTC 01/01/1970 $2")
to=$(date "+%s" -d "UTC 01/01/1970 $3")
from_pre=$(($from - 30))
if [ $from_pre -lt 0 ]
then
from_pre=0
fi
from_pre_command_print=$(date -u "+%T" -d #$from_pre)
from_command_print=$(date -u "+%T" -d #$(($from - $from_pre)))$(grep -o "\..*" <<< $2)
to_command_print=$(date -u "+%T" -d #$(($to - $from_pre)))$(grep -o "\..*" <<< $3)
command="ffmpeg "
for uri in $(youtube-dl -g $1)
do
command+="-ss $from_pre_command_print -i $uri "
done
command+="-ss $from_command_print -to $to_command_print $4"
echo "downloading with the following command:"
echo "$command"
$command
but the problem is its only precise to the full second.
I want to use it to download a bunch of very short clips (only one word long mostly) those are often below 1 second long.
I tryed to fix this by using milliseconds in the date.
But then i found out bash can only subtract with integers.
Here is what i tryed:
from=$(date "+%s.%3N" -d "UTC 01/01/1970 $2")
to=$(date "+%s.%3N" -d "UTC 01/01/1970 $3")
function diff {
diff="$(echo $from - 5 | bc)"
echo $diff
}
from_pre=$diff
echo $diff
but the workaround using bc didnt work because later in the script its again throwing errors because bash dosnt know what to do with non integers.
a sample command would look like this:
sh download_youtube.sh https://www.youtube.com/watch?v=dH3auOKyxio 00:06:28.230 00:06:28.740 clip004.mp4
and this works...if the the timeframe is more than 1 second.
Sadly i am out of knowlage here how to make it more precise.
This all is part of a project to make automated compilations of specific word from a youtube channel more on that here:
https://github.com/moeC137/video-recutter
I am very thankfull for every help
edit:
after a bit try an error i found out that this seams to work for me:
#!/bin/bash
#taken from https://unix.stackexchange.com/a/388148/48971
if [ $# -lt 4 ]; then
echo "Usage: $0 <youtube's URL> <HH:mm:ss.milisecs from time> <HH:mm:ss.milisecs to time> <output_file_name>"
echo "e.g.:"
echo "$0 https://www.youtube.com/watch?v=T1n5gXIPyws 00:00:25 00:00:42 intro.mp4"
exit 1
fi
echo "processing..."
from=$(date "+%s" -d "UTC 01/01/1970 $2")
to=$(date "+%s" -d "UTC 01/01/1970 $3")
from_pre=$(($from - 20))
#to_post=$(($to + 20))
if [ $from_pre -lt 0 ]
then
from_pre=0
fi
from_pre_command_print=$(date -u "+%T" -d #$from_pre)
from_command_print=$(date -u "+%T" -d #$(($from - $from_pre)))$(grep -o "\..*" <<< $2)
to_command_print=$(date -u "+%T" -d #$(($to - $from_pre)))$(grep -o "\..*" <<< $3)
#to_post_command_print=$(date -u "+%T.%3N" -d #$to_post)
command="ffmpeg "
for uri in $(youtube-dl -g $1)
do
command+="-ss $from_pre_command_print -i $uri "
done
command+="-ss $from_command_print -to $to_command_print $4"
echo "downloading with the following command:"
echo "$command"
$command
But i starting to think the orginal script actually works with milleseconds.
Because this:
sh download_youtube.sh https://www.youtube.com/watch?v=dH3auOKyxio 00:06:28.230 00:06:28.740 clip004.mp4
works, but when try to combine it with the script from here How to repeat a command for every line in a textfile with given arguments from the textfile (Bash?) it dosent use the milliseconds anymore.
Solved
The orginal Script worked. It just didnt like the "," in the timestamps, i replaced them with "." and now its working.
solved by replacing "," in timestamps with "."

Shell script to find the process state while excluding 'ps grep command'

can someone guide me writing shell script to find if the process is active or not? I have to exclude my own grep process filtering from ps command. I want to pass the process as a parameter,
script: (this is currently catching my own process)
#!/bin/sh
SERVICE=$1
echo $1
if ps ax | grep $SERVICE > /dev/null
then
echo "ok"
else
echo "not ok"
fi
example input tried: (though the process is dead I'm getting status as "ok")
./processchecker.sh '/usr/sbin/mysqld'
./processchecker.sh '[/usr/sbin/]mysqld' (i tried using square brackets using online suggestions but failed)
Please help.
You can use pgrep as well - which is a little more efficient:
#!/bin/sh
service=$1
status=0
if [ ! -z "$service" ]; then
pgrep "$service" >/dev/null; status=$?
if [ "$status" -eq 0 ]; then
echo "ok"
else
echo "not ok"
fi
fi
exit "$status"
It's better to have an appropriate exit value as well.
What you have is close, but you want to save the status of the grep command (via $?) and then if/else off of that value.
#!/bin/sh
SERVICE=$1
echo $1
ps ax | grep $SERVICE | grep -v ${0} > /dev/null
status=${?}
if [ "${status}" = "0" ]; then
echo "ok"
else
echo "not ok"
fi

Can't parse a string with brace expansion operations into a command

have some problem with shell script.
In our office we set up only few commands, that available for devs when they are trying ssh to server. It is configured with help of .ssh/authorized_keys file and available command for user there is bash script:
#!/bin/sh
if [[ $1 == "--help" ]]; then
cat <<"EOF"
This script has the purpose to let people remote execute certain commands without logging into the system.
For this they NEED to have a homedir on this system and uploaded their RSA public key to .ssh/authorized_keys (via ssh-copy-id)
Then you can alter that file and add some commands in front of their key eg :
command="/usr/bin/dev.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
The user will do the following : ssh testuser#server tail testserver.example.com/2017/01/01/user.log
EOF
exit 0;
fi
# set global variable
set $SSH_ORIGINAL_COMMAND
# set the syslog path where the files can be found
PATH="/opt/syslog/logs"
# strip ; or any other unwanted signs out of the command, this prevents them from breaking out of the setup command
if [[ $1 != "" ]]; then
COMMAND=$1
COMMAND=${COMMAND//[;\`]/}
fi
if [[ $2 != "" ]]; then
ARGU1=$2
ARGU1=${ARGU1//[;\`]/}
fi
if [[ $3 != "" ]]; then
ARGU2=$3
ARGU2=${ARGU2//[;\`]/}
fi
if [[ $4 != "" ]]; then
ARGU3=$4
ARGU3=${ARGU3//[;\`]/}
fi
# checking for the commands
case "$COMMAND" in
less)
ARGU2=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
exit 1;
fi
#echo " --------------------------------- LESS $FILE"
/usr/bin/less $FILE
;;
grep)
if [[ $ARGU2 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
if [[ $ARGU1 == "" ]]; then
echo "Pls give a string to search for"
exit 1
fi
ARGU2=${ARGU2//\.\./}
FILE=$PATH/$ARGU2
/usr/bin/logger -t restricted-command -- "------- $USER Executing grep $ARGU1 \"$ARGU2\" $FILE"
if [ ! -f $FILE ]; then
echo "File doesn't exist"
/usr/bin/logger -t restricted-command -- "$USER Executing $#"
exit 1;
fi
/bin/grep $ARGU1 $FILE
;;
tail)
if [[ $ARGU1 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
ARGU1=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
/usr/bin/logger -t restricted-command -- "$USER Executing $# ($FILE)"
exit 1;
fi
/usr/bin/tail -f $FILE
;;
cat)
ARGU2=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
exit 1;
fi
/bin/cat $FILE
;;
help)
/bin/cat <<"EOF"
# less LOGNAME (eg less testserver.example.com/YYYY/MM/DD/logfile.log)
# grep [ARGUMENT] LOGNAME
# tail LOGNAME (eg tail testserver.example.com/YYYY/MM/DD/logfile.log)
# cat LOGNAME (eg cat testserver.example.com/YYYY/MM/DD/logfile.log)
In total the command looks like this : ssh user#testserver.example.com COMMAND [ARGUMENT] LOGFILE
EOF
/usr/bin/logger -t restricted-command -- "$USER HELP requested $#"
exit 1
;;
*)
/usr/bin/logger -s -t restricted-command -- "$USER Invalid command $#"
exit 1
;;
esac
/usr/bin/logger -t restricted-command -- "$USER Executing $#"
The problem is next:
when i try to exec some command, it takes only first argument, if i do recursion in files by using {n,n1,n2} - it doesn't work:
[testuser#local ~]$ ssh testuser#syslog.server less srv1838.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
0
[testuser#local ~]$ ssh testuser#syslog.server less srv2010.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
11591
[testuser#local ~]$ ssh testuser#syslog.server less srv{1838,2010}.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
0
[testuser#local ~]$ ssh testuser#syslog.server less srv{2010,1838}.example.com/2017/02/21/local1.log |grep 'srv2010' | wc -l
11591
Could someone help me, how can i parse\count command arguments to make it work?
Thank you and have a nice day!
The number of arguments for a bash script would be $#. As a quick example:
#!/bin/bash
narg=$#
typeset -i i
i=1
while [ $i -le $narg ] ; do
echo " $# $i: $1"
shift
i=$i+1
done
gives, for bash tst.sh a b {c,d}
4 1: a
3 2: b
2 3: c
1 4: d
In your script, the command to execute (cat, less, ...) gets explicitly only the second argument to the script. If you want to read all arguments, you should do something like this (note: only a hint, removed all sorts of checks etc..)
command="$1"
shift
case $command in
(grep) pattern="$1"
shift
while [ $# -gt 0 ] ; do
grep "$pattern" "$1"
shift
done
;;
esac
note: added some quotes as comment suggested, but, being only a hint, you should carefully look at quoting and your checks in your own script.
Less command working now:
case "$COMMAND" in
less)
if [[ $ARGU1 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
FILES_LIST=${#:2}
FILE=(${FILES_LIST//\.\./})
for v in "${FILE[#]}";do
v=${v//[;\']/}
if [ ! -f $v ]; then
echo "File doesn't exist"
fi
/usr/bin/less $PATH/$v
done;;
tail command works too with 2 and more files, but i can't execute tail -f command on two files unfortunately.

Trigger a shell Script on log file change

I'm looking to trigger a command on xrdp session start and end, if /var/log/xrdp.log file get update with session started in last 10 minutes, I would like to trigger a shell script.
Example: Session Login Trigger.
[root#CentOS73-RDPDemo sp]# cat trigger-login.sh
#!/bin/bash
if [ $(( $(date +%s) - $(date +%s -r /var/log/xrdp.log) )) -le 180 ]; then
tail -n 4 /var/log/xrdp.log | grep -i "socket: 11"
sh /usr/src/sp/sql-login.sh
fi
Example: Session Logout Trigger
[root#CentOS73-RDPDemo sp]# cat trigger-logout.sh
#!/bin/bash
if [ $(( $(date +%s) - $(date +%s -r /var/log/xrdp.log) )) -le 180 ]; then
tail -n 4 /var/log/xrdp.log | grep -i "socket: 12"
sh /usr/src/sp/sql-logout.sh
fi
Write a script (say main.sh) which checks if there is any update in file (var/log/xrdp.log). If there is any update in file, call your desired scripts (trigger-login.sh and trigger-logout.sh).
You can do it using stat or md5sum
Example for reference (main.sh).
#!/bin/bash
touch /tmp/checkMD5
nchksum=`md5sum a.out | awk -F " " '{print $1}'`
ochksum=`cat /tmp/checkMD5`
if [ "$nchksum" == "$ochksum" ]; then
echo "both are same"
else
sh trigger-login.sh
sh trigger-logout.sh
fi
echo $nchksum >/tmp/checkMD5
schedule a crontab job which will run the main.sh script in every 10 minutes.

Bash error reports

Ok, I can get this to run and put the file on the remote server. However when it does run, I want it to echo a Transfer failed, Transfer OK, Zero bytes in file and No such file or directory. It just runs down the code and sends an email of the last entry which is no such file or directory when clearly the file transferred to the server. What am I doing wrong ??
Thx in advance, I thank you.
#!/bin/sh
HOST=10.10.1.2
USER='test'
RECIP="user#somemail.com"
cd /home/test
FILE=ARG$(date '+%Y%m%d').txt
BYTES=`stat -c%s $FILE`
CONNECTION=`netstat -an | grep ESTABLISHED | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | awk '{printf("%s\t%s\t",$2,$1) ; for (i = 0; i < $1; i++) {printf("*")}; print ""}'`
RUN_AS=`whoami`
RESULT=`sftp $USER#$HOST <<EOF
FILE=ARG$(date '+%Y%m%d').txt
cd /998979/DES
if [ -e $FILE ]; then
put $FILE
EOF`
echo $CONNECTION "Connection to network is established."
ls | xargs wc -wl for file in *; echo $FILE done
if [ $? -eq 0 ]; then
echo "$RESULT" "Transfer of file failed. `date`"
SBJ="Transfer of file failed `date`"
fi
echo "$RESULT" "Transfer OK"
if [ $? -eq 0 ]; then
SBJ="Transfer OK. `date`"
echo "$RESULT" "Transfer OK"
fi
if \[ ! -s ${FILE} \]; then
echo "File: ${FILE} is not present or a ZERO byte file"
SBJ="Failed to upload. Zero bytes in file. `date`" # zero bytes sent
fi
if [ -a $FILE ]; then
echo "$RESULT" "No such file or directory"
SBJ="No such file or directory. `date`"
fi
BODY="Process Report.......
SRC SERVER:`hostname`
DST SEVER: TESTSERVER
SCRIPT: /usr/local/bin/put.sh
RUN AS: "$RUN_AS"
RESULT: "$RESULT" "$FILE"
CONNECTION: "$CONNECTION"
FILENAME: "$FILE"
BYTES: "$BYTES"
DATE/TIME: `date`"
echo "$BODY" | mail -s "$SBJ" "$RECIP"
You can use /bin/sh -xv yourshellscript.sh to understand what is happening.
And you could log important messages to the system log using logger
count=$?
if [ $count -eq 0 ]; then
echo "$RESULT" "Transfer of file failed.
`date`" SBJ="Transfer of file failed `date`"
else
echo "$RESULT" "Transfer OK"
fi
Assign the result to a variable, Also, try to use exit when you don't need to do more processing.

Resources