bash script, ask for arg if not provided - bash

I have created a script that will check to see if a user you provide is logged on and display the duration of the session if logged on. What i need to do now is if no argument (username) is provided when the command is issued, ask for one and have the same results as if you have provided one.
Here is what I have:
name=$(cat /etc/passwd | grep $1 | cut -d':' -f5 | tr ':' ' ' | sed 's/,//' | sed 's/^\([^ ]*\) \([^ ]*\)/\2 \1/' | sort -t' ' -k3,3)
terminal=$(who | grep $1 | cut -d' ' -f3)
loginHour=$(who | grep $1 | cut -c30-31)
loginMin=$(who | grep $1 | cut -c33-34)
loginMins=$((loginHour * 60 + loginMin))
nowHour=$(date +%R | cut -c1-2)
nowMin=$(date +%R | cut -c4-5)
nowMins=$((nowHour * 60 + nowMin))
totalMins=$((nowMins - loginMins))
hoursOn=$((totalMins / 60))
minsOn=$((totalMins % 60))
clear
echo
if [[ $# -eq 1 ]] ; then
grep -q $1 /etc/passwd
if grep -q $1 /etc/passwd ; then
clear
echo
if who | grep $1 > /dev/null ; then
echo "$name" is currently logged on to terminal "$terminal" and has been for "$hoursOn" hour"(s)" and "$minsOn" minute"(s)".
echo
exit 0
else
echo "$name" is NOT currently logged on.
echo
exit 1
fi
else
echo The user you entered is not a valid user on this system.
echo
exit 2
fi
fi
I had an attempt before but was not the desired result so I removed it out of confusion.

if [[ $# -eq 0 ]]
then
read -p "Enter Name: " username
else
username=$1
fi
then replace all subsequent references to $1 by $username

You can also abort if no name given
# : does nothing it just forces the evaluation
: ${1:?"Need to provide name to script"}

Related

if statement function to many argumnets

I've overlooked my program for any mistakes and can't find any. Usually when I run into a mistake with BASH the interpreter is off on where the mistake is. I'm trying to customize this script from SANS InfoSec Using Linux Scripts to Monitor Security. Everything is fine until the part where the check function looks at the different protocols. When I uncomment them I get the error: ./report: line 41: [: too many arguments. Here is the program...
#!/bin/bash
if [ "$(id -u)" != "0" ]; then
echo "Must be root to run this script!"
exit 1
fi
##### CONSTANTS -
report=/home/chron/Desktop/report.log
#router=/home/chron/Desktop/router.log
red=`tput bold;tput setaf 1`
yellow=`tput bold;tput setaf 3`
green=`tput bold;tput setaf 2`
blue=`tput bold;tput setaf 4`
magenta=`tput bold;tput setaf 5`
cyan=`tput bold;tput setaf 6`
white=`tput sgr0`
##### FUNCTIONS -
pingtest() {
ping=`ping -c 3 localhost | tail -2`
loss=`echo $ping | cut -d"," -f3 | cut -d" " -f2`
delay=`echo $ping | cut -d"=" -f2 | cut -d"." -f1`
if [ "$loss" = "100%" ]; then
echo -n $red$1$white is not responding at all | mail -s'REPORT' localhost
echo 'You have mail in /var/mail!'
echo `date` $1 is not responding at all >> $report
elif [ "$loss" != "0%" ]; then
echo $yellow$1$white is responding with some packet loss
else
if [ "$delay" -lt 100 ]; then
echo $green$1$white is responding normally
else
echo $yellow$1$white is responding slow
fi
fi
}
check() {
if [ "$2" != "" -a "$2" $3 ] ; then
echo -n $green$1$white' '
else
echo -n $red$1$white' '
echo `date` $1 was not $3 >> $report
fi
}
##### __MAIN__ -
pingtest localhost # hostname or ip
echo "Server Configuration:"
check hostname `hostname -s` '= localhost'
check domain `hostname -d` '= domain.com'
check ipaddress `hostname -I | cut -d" " -f1` '= 10.10.0.6'
check gateway `netstat -nr | grep ^0.0.0.0 | cut -c17-27` '= 10.10.0.1'
echo
echo "Integrity of Files:"
check hostsfile `md5sum /etc/hosts | grep 7c5c6678160fc706533dc46b95f06675 | wc -l` '= 1'
check passwd `md5sum /etc/passwd | grep adf5a9f5a9a70759aef4332cf2382944 | wc -l` '= 1'
#/etc/inetd.conf is missing...
echo
#echo "Integrity of Website:"
#check www/index.html `lynx -reload -dump http://<LOCALIP> 2>&1 | md5sum | cut -d" " -f1 '=<MD5SUM>'
#echo
echo "Incoming attempts:"
#lynx -auth user:password -dump http://10.10.0.1 >> $router 2>&1
check telnet `grep \ 23$ $PWD/router.log | wc -l` '= 0'
check ftp `grep \ 21$ $PWD/router.log | wc -l` '= 0'
check ssh `grep \ 22$ $PWD/router.log | wc -l` '=0'
check smtp `grep \ 25$ $PWD/router.log | wc -l` '=0'
check dns `grep \ 53$ $PWD/router.log | wc -l` '=0'
echo
Some of the lines are commented out for later tweaking. Right now my problem is with the protocols. Not sure what's wrong because it looks like to me there are 3 arguments for the function.
In your last three calls to check, you are missing the required space between the operator and the operand.
check ssh `grep \ 22$ $PWD/router.log | wc -l` '=0'
check smtp `grep \ 25$ $PWD/router.log | wc -l` '=0'
check dns `grep \ 53$ $PWD/router.log | wc -l` '=0'
The final argument to all of these should be '= 0'.
However, this is not a good way to structure your code. If you really need to parameterize the comparison fully (all your calls use = as the operation), pass the operator as a separate argument. Further, written correctly, there is no need to pre-check that $2 is a non-empty string.
check() {
if [ "$2" "$3" "$4" ] ; then
printf '%s%s%s ' "$green" "$1" "$white"
else
printf '%s%s%s ' "$red" "$1" "$white"
printf '%s %s was not %s\n' "$(date)" "$1" "$3" >> "$report"
fi
}
Then your calls to check should look like
check hostname "$(hostname -s)" = localhost
check domain "$(hostname -d)" = domain.com
check ipaddress "$(hostname -I | cut -d" " -f1)" = 10.10.0.6
check gateway "$(netstat -nr | grep ^0.0.0.0 | cut -c17-27)" = 10.10.0.1
etc
Run your code through http://shellcheck.net; there are a lot of things you can correct.
Here is my other problem. I changed it up a bit just to see what's going on.
router=/home/chron/Desktop/router.log
check() {
if [ "$2" "$3" "$4" ]; then
printf "%s%s%s" "$green" "$1" "$white"
else
printf "%s%s%s" "$red" "$1" "$white"
printf "%s %s was not %s\n" "$(date)" "$1" $3" >> report.log
fi
check gateway "$(route | grep 10.10.0.1 | cut -c17-27)" = 10.10.0.1
check telnet "$(grep -c \ 23$ $router)" = 0
check ftp "$(grep -c \ 21$ $router)" = 0
check ssh "$(grep -c \ 22$ $router)" = 0
check smtp "$(grep -c \ 25$ $router)" = 0
check dns "$(grep -c \ 53$ $router)" = 0

BASH: Remove newline for multiple commands

I need some help . I want the result will be
UP:N%:N%
but the current result is
UP:N%
:N%
this is the code.
#!/bin/bash
UP=$(pgrep mysql | wc -l);
if [ "$UP" -ne 1 ];
then
echo -n "DOWN"
else
echo -n "UP:"
fi
df -hl | grep 'sda1' | awk ' {percent+=$5;} END{print percent"%"}'| column -t && echo -n ":"
top -bn2 | grep "Cpu(s)" | \sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | \awk 'END{print 100 - $1"%"}'
You can use command substitution in your first sentence (notice you're creating a subshell in this way):
echo -n $(df -hl | grep 'sda1' | awk ' {percent+=$5;} END{print percent"%"}'| column -t ):

BASH better way to monitor files

I've made a Bash script to monitor some server log files for certain data and my method probably isn't the most efficient.
One section specifically bugs me is that I have to write a newline to the monitored log so that the same line wont be read over continually.
Feedback would be greatly appreciated!
#!/bin/bash
serverlog=/home/skay/NewWorld/server.log
onlinefile=/home/skay/website/log/online.log
offlinefile=/home/skay/website/log/offline.log
index=0
# Creating the file
if [ ! -f "$onlinefile" ]; then
touch $onlinefile
echo "Name Date Time" >> "$onlinefile"
fi
if [ ! -f "$offlinefile" ]; then
touch $offlinefile
echo "Name Date Time" >> "$offlinefile"
fi
# Functions
function readfile {
# Login Variables
loginplayer=`tail -1 $serverlog | grep "[INFO]" | grep "joined the game" | awk '{print $4}'`
logintime=`tail -1 $serverlog | grep "[INFO]" | grep "joined the game" | awk '{print $2}'`
logindate=`tail -1 $serverlog | grep "[INFO]" | grep "joined the game" | awk '{print $1}'`
# Logout Variables
logoutplayer=`tail -1 $serverlog | grep "[INFO]" | grep "left the game" | awk '{print $4}'`
logouttime=`tail -1 $serverlog | grep "[INFO]" | grep "left the game" | awk '{print $2}'`
logoutdate=`tail -1 $serverlog | grep "[INFO]" | grep "left the game" | awk '{print $1}'`
# Check for Player Login
if [ ! -z "$loginplayer" ]; then
echo "$loginplayer $logindate $logintime" >> "$onlinefile"
echo "Player $loginplayer login detected" >> "$serverlog"
line=`grep -rne "$loginplayer" $offlinefile | cut -d':' -f1`
if [ "$line" > 1 ]; then
sed -i "$line"d $offlinefile
unset loginplayer
unset line
fi
fi
# Check for Player Logout
if [ ! -z "$logoutplayer" ]; then
echo "$logoutplayer $logoutdate $logouttime" >> "$offlinefile"
echo "Player $loginplayer logout detected" >> "$serverlog"
line=`grep -rne "$logoutplayer" $onlinefile | cut -d':' -f1`
if [ "$line" > 1 ]; then
sed -i "$line"d $onlinefile
unset logoutplayer
unset line
fi
fi
}
# Loop
while [ $index -lt 100 ]; do
readfile
done
Thanks!
instead of using multiple
tail -n 1 file
try the following construct:
tail -f file | while read line;do
echo "read: $line"
done
it will be much more reliable...and won't read the same line twice ;)
note: by using new processes of grep/awk/etc you are burning away processes...it's not that it is critical, but usually process creation is expensive...but if new lines occur rarely it's perfectly fine
where i want'ed to get is: if you are intrested, take a look at bash builting string manipulator function replace $(x/aa} ${x//aa} and friends..or try to use extended regexpes with grep

Bash error echo a command

I have a problem. I need to show a echo from a while, I use two echo the first one work but the second it give a error.
#!/bin/bash
conexiuni="/tmp/conexiuni"
if [ "$1" != "" ]; then
netstat -tuan | grep $1 | grep ESTAB | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n > $conexiuni
else
netstat -tuan | grep ESTAB | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n > $conexiuni
fi
cat $conexiuni | while read line
do
con=`echo ''$line'' | awk '{print $1}'`
ip=`echo ''$line'' | awk '{print $2}'`
if [ "$con" -gt "4" ]; then
`echo -e "$ip" >> /var/log/drop_sc_ip`
`echo -e "$ip"`
fi
done
if [ -f "$conexiuni" ];
then
`rm -rf $conexiuni`
fi
The error is :
./show_conn: line 15: 8.97.80.2: command not found
./show_conn: line 15: 8.76.109.13: command not found
./show_conn: line 15: 8.33.15.2: command not found
./show_conn: line 15: 9.118.226.3: command not found
You can write this part without the backticks:
if [ "$con" -gt "4" ]; then
echo -e "$ip" >> /var/log/drop_sc_ip
echo -e "$ip"
fi
also same in this part:
rm -rf $conexiuni
with the backticks, it first executes what is inside the backticks and then tries to execute the output of the backticks.
and change the loop:
while read con ip
do
if [ "$con" -gt "4" ]; then
echo -e "$ip" >> /var/log/drop_sc_ip
echo -e "$ip"
fi
done < $conexiuni

Too many arguments error in shell script

I am trying a simple shell script like the following:
#!/bin/bash
up_cap=$( cat result.txt | cut -d ":" -f 6,7 | sort -n | cut -d " " -f 2 | sort -n)
down_cap=$( cat result.txt | cut -d : -f 6,7 | sort -n | cut -d " " -f 6| sort -n)
for value in "${down_cap[#]}";do
if [ $value > 80000 ]; then
cat result.txt | grep -B 1 "$value"
fi
done
echo " All done, exiting"
when I execute the above script as ./script.sh, I get the error:
./script.sh: line 5: [: too many arguments
All done, exiting
I have googled enough, and still not able to rectify this.
You want
if [ "$value" -gt 80000 ]; then
You use -gt for checking if A is bigger than B, not >. The quotation marks I merely added to prevent the script from failing in case $value is empty.
Try to declare variable $value explicitly:
declare -i value
So, with the dominikh's and mine additions the code should look like this:
#!/bin/bash
up_cap=$( cat result.txt | cut -d ":" -f 6,7 | sort -n | cut -d " " -f 2 | sort -n)
down_cap=$( cat result.txt | cut -d : -f 6,7 | sort -n | cut -d " " -f 6| sort -n)
for value in "${down_cap[#]}";do
declare -i value
if [ $value -gt 80000 ]; then
cat result.txt | grep -B 1 "$value"
fi
done
echo " All done, exiting"

Resources