Shell script printf not printing variables - linux

i'm new in stackoverflow, I’m trying to print something like that.
From: email#domain.com
To: rcpt#domain.com
Date: date
LOG_ID: ID
I’m reading the Postfix logs, which contains the following text:
Oct 28 10:42:48 host postfix/pickup[8779]: 4B0782A016E: uid=1000 from=<from#from.com>
Oct 28 10:42:48 host postfix/cleanup[14607]: 4B0782A016E: message-id=<20211028134248.4B0782A016E#mail.democloud.com>
Oct 28 10:42:48 host postfix/qmgr[2656]: 4B0782A016E: from=<from#from.com>, size=400, nrcpt=1 (queue active)
Oct 28 10:42:50 host postfix/smtp[14610]: 4B0782A016E: to=<rcpt#rcpt.com>, relay=gmail-smtp-in.l.google.com[172.217.192.26]:25, delay=1.7, delays=0/0/1.1/0.64, dsn=2.0.0, status=sent (250 2.0.0 OK 1635428569 jl7si2828702qvb.144 - gsmtp)
Oct 28 10:42:50 host postfix/qmgr[2656]: 4B0782A016E: removed
To perform the task I created the following shell script:
#!/bin/bash
if [ $# -ne 1 ] ; then
echo "
Ingresar cuenta de correo
Ej.: $0 rcpt#rcpt.com
"
exit 1
fi
RCPT="$1"
MAILOG="/var/log/mail.log"
STATS_DIR="/tmp"
echo -e "\n==== Detalle Total de Envios a <$1> ==== "
echo
QUEUEID=`grep -w "to=<${RCPT}>" ${MAILOG} | grep -E "status=(sent|deferred|bounced)" | awk -F"smtp" '{print $2}' | cut -d":" -f2 | sed -e s'/ //'g | sort | uniq`
for QID in ${QUEUEID} ; do
EMAIL=`grep ${QID} /var/log/mail.log | sed -r 's/^([^;]*;)[^;]*;/\1/' | awk 'BEGIN{FS=OFS=" "} {print $7}' | grep -w "from=" | tr -d , | grep -E -o "\b[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b"`
RCPT=`grep ${QID} /var/log/mail.log | sed -r 's/^([^;]*;)[^;]*;/\1/' | awk 'BEGIN{FS=OFS=" "} {print $7}' | grep -w "to=" | tr -d , | grep -E -o "\b[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b"`
DATE=`grep ${QID} /var/log/mail.log | sed -r 's/^([^;]*;)[^;]*;/\1/' | awk 'BEGIN{FS=OFS=" "} {print $1, $2,$3}'`
printf "From: $s\nDestinatario: $s\nFecha: $s\nLOG_ID: $s\n\n" "${EMAIL}" "${RCPT}" "${DATE}" "${QID}"
done
exit 0
My problem is running printf, the script output is empty.
What’s the problem? Can you help me improve the script, thank you.
Regards,

Related

Storing values using if inside while loop BASH

I am working with a new script that reads from a log file and then stores the ips which match one of the two patterns:
Either its a failed attempt or its a failed attempt using ssh.
My code runs good, but the problem is that when the while condition finishes, when I want to call the variable which stores all the IPs it only shows the last one.
#!/bin/bash
while IFS=";" read -r p || [ -n "$p" ]
do
first=$(echo $p | sed -E -e "s/[[:blank:]]+/;/g" | cut -d ";" -f 6)
if [[ $first == "Failed" ]];
then
echo "ADVERTENCIA - ATAC DDOS - !"
x="$(echo $p | sed -E -e "s/[[:blank:]]+/;/g" | awk -F ";" '{print $11}') "
elif [[ $first == "pam_unix(sshd:auth):" ]];
then
echo "ADVERTENCIA - LOGUEIG DE SSH - ! !"
y="$(echo $p | sed -E -e "s/[[:blank:]]+/;/g" | awk -F ";" '{print $15}' | cut -b 7-19)"
fi
done < syslog.txt
(IFS=""; sort <<< "$x") | uniq -c
#This comand only prints the last ip, but I want to print the whole IP list.
My syslog text:
Apr 15 00:00:11 spark sshd[7812]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.25.208.92 user=root
Apr 15 11:38:58 spark sshd[13924]: Failed password for root from 183.3.202.111 port 22064 ssh2
Apr 15 11:38:58 spark sshd[13924]: Failed password for root from 183.3.202.111 port 22064 ssh2
Apr 15 00:00:11 spark sshd[7812]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.25.208.92 user=root
Current output:
1 183.3.202.111
1 218.25.208.92
What it should be really printing:
2 183.3.202.111
2 218.25.208.92
Each time you assign a value to x you're overwriting the previous version:
x="$(echo $p | sed -E -e "s/[[:blank:]]+/;/g" | awk -F ";" '{print $11}') "
Assuming your intention is to append new ip's onto the end of x, you have a few options, eg:
# use "+=" to append to variable
x+="$(echo $p | sed -E -e "s/[[:blank:]]+/;/g" | awk -F ";" '{print $11}') "
# reference variable in the assignment, eg, x="${x}..."
x="${x}$(echo $p | sed -E -e "s/[[:blank:]]+/;/g" | awk -F ";" '{print $11}') "

Modify the output of the command "last"

I want to make a program in bash to display the output of last with this format:
username | number of sessions | duration of sessions | maximum session length
I already did the first two columns but don´t know how to do the rest.
This is the code I wrote for the username and number of sessions:
last |& tee last.txt
cut -d' ' -f1,2 last.txt > last1.txt
thanks
You can try with something like this. Its not perfect but very close :
#!/bin/bash
unique_users="$( last | awk ' {print $1} ' | sort | uniq | grep -v 'shutdown\|wtmp\|reboot' | awk 'NF' )"
for user in $unique_users
do
number_of_sessions="$( last $user | awk '{print $NF}' | grep '^(' | tr -d '()' | wc -l )"
total_mins="$( last $user | awk '{print $NF}' | grep '^(' | tr -d '()' | awk '{ split($1, t, ":"); print (t[1]*60+t[2]) }' | awk '{ sum+=$1}END{print sum/60}' )"
max_length="$( last $user | awk '{print $NF}' | grep '^(' | tr -d '()' | awk '{ split($1, t, ":"); print (t[1]*60+t[2]) }' | sort -rn | head -1 | awk '{ sum+=$1}END{print sum/60}')"
printf "$user | $number_of_sessions | $total_mins | $max_length\n"
done
Regards!
I'm assuming last output same as Mint19
owner tty7 :0 Sun Nov 17 06:18 gone - no logout
owner tty7 :0 Sun Nov 10 11:13 - crash (6+18:34)
owner tty7 :0 Thu Nov 7 14:10 - 11:11 (2+21:00)
owner pts/1 :0 Wed Nov 6 21:48 - 21:48 (00:00)
owner pts/1 :0 Wed Nov 6 21:37 - 21:40 (00:03)
The file is sorted by timestamp, and the 10th column contain the session duration: either (HH:MM), or (DAYS+HH:MM). Small awk will do the trick. Script only count terminated session - ignoring crashed/still running sessions.
Total is session time in minutes.
#! /usr/bin/awk -f
{
id=$1
if ( match($10, /\(([0-9]+)\+\)?([0-9][0-9]):([0-9][0-9])/, a) ) {
dur_min = a[1]*24*60 + a[3] * 60 + a[4] ;
s_count[id]++ ;
s_total[id] += dur_min
if ( dur_min > s_max[id] ) s_max[id] = dur_min
}
}
END {
print "ID", "Count", "Total(min)", "Max(min)"
for (id in s_count) {
print id, s_count[id], s_total[id], s_max[id]
} ;
}

Check MAC from log

I currently have a script that checks the MAC address, tt looks like this
"m"|"-m" )
if [ ! -n "$2" ]
then
echo "Enter MAC address"
exit 0
fi
out1=`cat $dhcp_files/* | grep -i "$2" 2>/dev/null`
ip=`cat $dhcp_files/* | grep -i "$2" | awk '{print $8}' | sed s/\;//g 2>/dev/null`
out=` grep -i $ip $shapy/* | awk '{print $8}' 2>/dev/null`
echo -en ''$out1' on '$out' \n'
this is done like that: ./mac_check -m 00:00:00:00:00:00
The result of this script:
host Jon_Rosewelt_6_5 { hardware ethernet 00:1d:4e:b5:d4:10; fixed-address 192.168.101.19; } on eth4
but I would like to do to the script received any form of mac address
aka. ./check_mac -m 001d.4eb5.d410 **or** 001d4eb5d410 **or** 00-1d-4e-b5-d4-10
How can I do that?
With GNU sed and Solaris sed:
echo 001d.4eb5.d410 | sed 's/[^0-9a-f]//g;s/../&:/g;s/:$//'
echo 001d4eb5d410 | sed 's/[^0-9a-f]//g;s/../&:/g;s/:$//'
echo 00-1d-4e-b5-d4-10 | sed 's/[^0-9a-f]//g;s/../&:/g;s/:$//'
echo 00:1d:4e:b5:d4:10 | sed 's/[^0-9a-f]//g;s/../&:/g;s/:$//'
Output:
00:1d:4e:b5:d4:10
00:1d:4e:b5:d4:10
00:1d:4e:b5:d4:10
00:1d:4e:b5:d4:10
With your code:
"m"|"-m" )
mac="$2" # added
if [ ! -n "$mac" ] # changed
then
echo "Enter MAC address"
exit 0
fi
mac="$(echo "$mac" | sed 's/[^0-9a-f]//g;s/../&:/g;s/:$//')" # added
out1=`cat $dhcp_files/* | grep -i "$mac" 2>/dev/null` # changed
ip=`cat $dhcp_files/* | grep -i "$mac" | awk '{print $8}' | sed s/\;//g 2>/dev/null` # changed
out=` grep -i $ip $shapy/* | awk '{print $8}' 2>/dev/null`
echo -en ''$out1' on '$out' \n'

how to cut substring from linux command "who"

command who returns list of users logged to server
[admin#DB01ATK ~]$ who
adm_drodmann pts/3 2015-07-01 08:57 (10.129.12.77)
adm_ssmith pts/4 2015-07-01 02:11 (10.129.12.76)
adm_kholdman pts/2 2015-06-30 23:08 (10.129.12.45)
the point is to assign to variable, value of username($1) where terminal($2) is result from command
ps aux | grep screen
question asked question answered:
PTS=$(awk '{print $7}' <<< $(ps aux | grep screen) )
who | while read CMD;
do
res=$(awk '{print $2}' <<< "$CMD")
if [ "$res" = "$PTS" ]
then
echo "logged as $(awk '{print $1}' <<< "$CMD")"
fi
done;
:-)
As per your comment I expand my solution. You want to say:
ptw=$(ps aux | awk '/screen/ {print $7}')
while IFS=read -r user res _;
do
[ "$res" = "$PTS" ] && echo "logged as $user"
done < <(who)

Linux script help needed

I am trying to create a script that will use the /etc/passwd file to create a listing like this:
Full Name: Blah Blah User Account: bblah User ID: 5000 Last logged in: Sun Feb 21 18:13
Full Name: Mike Mike User Account: mmike User ID: 5001 Last logged in: Sun Feb 21 18:13
With my script, I get it to show
Full Name: Blah Blah User Account: bblah User ID: 1000
because I grep the 1000 accounts in my passwd file. As soon as I do the 5000 series, I get all the full names, then all the user accounts, and then all the user ids listed. How do I go about fixing this? How do I go about adding the "Last logged in" bit?
Is there a way to do this without using awk?
Script so far is:
#!/bin/bash
passfile=/etc/passwd
for i in $(grep 5000 ${passfile} | cut -d : -f 5)
do
account=$(grep 5000 /etc/passwd | cut -d : -f 3)
username=$(grep 5000 /etc/passwd | cut -d : -f 1)
echo Full Name:${i} Username: ${username} User ID: ${account} Last login: ${lastlogin)
done
Last logged in is done by last command:
last username
Use this:
#!/bin/bash
echo -en "BEGIN{\n}{\n system(var)\n}\n" > h.awk
while read in; \
do \
uname=`echo $in | sed -r 's/:/\ /g' | awk '{print $1}'`; \
p1=`echo $in | sed -r 's/:/\ /g' | awk '{print "name: "$5, "username: "$1, "id: "$3}'`; \
p2=`echo | awk -f ./h.awk var="last $uname| head -n 1"|awk '{print $5 $6}'`; \
echo $p1 last login: $p2; \
done < /etc/passwd
If you need more detail of last login to be prompted, use this one:
echo -en "BEGIN{\n}{\n system(var)\n}\n" > h.awk
while read in; \
do \
uname=`echo $in | sed -r 's/:/\ /g' | awk '{print $1}'`; \
p1=`echo $in | sed -r 's/:/\ /g' | awk '{print "name: "$5, "username: "$1, "id: "$3}'`; \
p2=`echo | awk -f ./h.awk var="last $uname| head -n 1"|awk '{print $4" "$5 $6" "$7}'`; \
echo $p1 last login: $p2; \
done < /etc/passwd

Resources