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
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}') "
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]
} ;
}
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'
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)
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