Send message to group in Linux - linux

I found the way to send message to currently logged in user by username:
who | grep username | cut -c1-20 | while read line; do printf "Message Text" | write $line ; done
However, is there anyway I can send message to currently logged in user by group?
Thanks for your help.

So... To send a message to every logged in user in a particular group, on every tty they're logged in to...
#!/bin/sh
usage() {
cat <<-EOT
Usage: writegroup groupname [message]
where [message] will be taken from stdin if not provided on the command line.
EOT
}
if [ $# -eq 0 ]; then
usage
exit 1
fi
groupname="$1"
shift
message="$*"
if [ -z "$message" ]; then
read message
fi
who | while read user tty junk; do
if groups "$user" | grep -wq "$groupname"; then
echo "$message" | write "$user" "$tty"
fi
done

Provided you set the variable group to the group you're interested in, you can try this:
for i in $(who -u | cut -d " " -f1 | sort | uniq); do if echo $(groups $i | cut -d " " -f3-) | grep $group >/dev/null; then echo "Message Text" | write $i; fi; done
$(who -u | cut -d " " -f1 | sort | uniq) gives the list of user logged in.
$(groups $i | cut -d " " -f3-) gives all groups a user belongs to.
The grep statement will reduce the list to the user belonging to the $group

Related

Problem with putting value in array in bash

I would like to make array which put users in a time using for loop. For example:
y[1]="user1"
y[2]="user2"
...
y[n]="usern"
I tried to do it like this
#!/bin/bash
x=$(who | cut -d " " -f1 | sort | uniq | wc -l)
for (( i=1; i<=$x; i++ )); do
y[$i]=$(who | cut -d " " -f1 | sort | uniq | sed -n '$ip')
p[$i]=$(lsof -u ${y[$i]} | wc -l)
echo "Users:"
echo ${y[$i]}
echo -e "Number of launched files:\n" ${p[$i]}
done
Most likely I'm using command "sed" wrong.
Can you help me?
Indeed your sed command seems to be a bit off. I can't really guess what you're trying to do there. Besides that, I'm wondering why you're executing who twice. You can make use of the data first obtained in the following manner.
#!/bin/bash
# define two arrays
y=()
p=()
#x=0
while read -r username; do
y+=("$username")
p+=($(lsof -u $(id -u "$username") | wc -l))
echo -e "User:\n${y[-1]}"
echo -e "Open files:\n${p[-1]}"
# The -1 index is the last index in the array, but you
# could uncomment the x=0 variable and the line below:
#((x++))
done <<< $(who | cut -d " " -f1 | sort | uniq)
echo "Amount of users: $x"
exit 0

Bash: how to check if there is only one root id and all user UIDs are unique?

i have this bash script here that i'm trying to modify to check if there is only one root id, is it vulnerable and currently, this script only checks if there is a duplicate uid and display the users that shares the same uid. Thanks in advance! :)
Bash Script:
#!/bin/bash
/bin/cat /etc/passwd| /bin/cut -f3 -d":" | /bin/sort -n | /usr/bin/uniq-c | while
read x ; do
[ -z "${x}" ] && break
set -$x
if [ $1 -gt1 ]; then
users=`/bin/gawk -F: '($3 == n) { print $1 }' n=$2 /etc/passwd| /usr/bin/xargs`
echo "Duplicate UID ($2): ${users}"
fi
done
Expected Output:
Audit criteria: There is only one root id
Vulnerability: Yes
Details: See below
root:!:0:0::/:/usr/bin/bash
jdoe:*:0:1:John Doe:/home/jdoe:/usr/bin/bash
You can simplify your script greatly because all you are looking for is user id 0, which is root:
#!/bin/bash
root_count=$(cut -f3 -d":" /etc/passwd | grep -wc 0)
if [[ $root_count > 1 ]]; then
users=$(awk -F: '($3 == 0) { print $1 }' /etc/passwd | xargs)
echo "Duplicate roots: ${users}"
fi
You can use awk to find that out:
if ! awk -F: '$3==0{c++}END{exit !(c<2)}' /etc/passwd ; then
echo "More than one user with uid 0"
fi

How to select log levels to the output of a bash script

In the script i have written, the output is sent to a log file mySysMonitor.log. I want the user of this script to be able to choose what log levels(debug or info) to be sent to the log file. How do i do this. Take the script below as an example.
#!/bin/bash
processKD(){
printf "\nCURRENT PROCESSES \r"
ps -eo user,pid,pcpu,pmem,start | sort -rk 3,4 | head -n 11
echo "TOTAL NUMBER OF RUNNING PROCESSES: $(ps aux | wc -l)"
}
loggedInKD(){
printf "\nUSERS CURRENTLY LOGGED IN\r"
echo "Number of users logged in: $(w | head -n 1 | cut -d"," -f 3)"
who
}
processKd >> mySysMonitor.log
loggedInKd >> mySysMonitor.log
you can use something like this;
#!/bin/bash
processKD(){
printf "\nCURRENT PROCESSES \r"
ps -eo user,pid,pcpu,pmem,start | sort -rk 3,4 | head -n 11
echo "TOTAL NUMBER OF RUNNING PROCESSES: $(ps aux | wc -l)"
}
loggedInKD(){
printf "\nUSERS CURRENTLY LOGGED IN\r"
echo "Number of users logged in: $(w | head -n 1 | cut -d"," -f 3)"
who
}
LOG_LEVEL="info"
#LOG_LEVEL=$1 #with parameter ./script info
#LOG_LEVEL="debug"
if [ "$LOG_LEVEL" == "info" ]; then
loggedInKd >> mySysMonitor.log
fi
if [ "$LOG_LEVEL" == "debug" ]; then
processKd >> mySysMonitor.log
loggedInKd >> mySysMonitor.log
fi

BASH syntax error at line 1: `then' unmatched

eval: syntax error at line 1: `then' unexpected
Hi, I am having issues with this particular loop and couldn't find a solution to it, any ideas why?
getent passwd | cut -f1 -d":" | sort -n | uniq -c |\ while read x ; do [ -z "${x}" ] && break set - $x if [ $1 -gt 1 ]; then gids=`getent passwd |\ nawk -F: '($1 == n) { print $3 }' n=$2 | xargs` echo "Duplicate Group Name ($2): ${gids}" fi done
If you run the code through shellcheck and correct the errors which it shows (except for one problematic warning), the code will become:
getent passwd | cut -f1 -d":" | sort -n | uniq -c |
while read -r x ; do
[ -z "${x}" ] && break
set - $x
if [ "$1" -gt 1 ]; then
gids=$(getent passwd | nawk -F: '($1 == n) { print $3 }' n="$2" | xargs)
echo "Duplicate Group Name ($2): ${gids}"
fi
done
The code still seems to have issues, one of which is that it looks for duplicate user names but the print out claims that it found duplicate group names.
I would suggest replacing the above with:
getent passwd | awk -F: '{c[$1]++; uids[$1]=uids[$1]" "$3} END{for (name in c) if (c[name]>1) printf "Duplicate User Name (%s):%s\n",name, uids[name]}'
How the awk code works
In the output of getent passwd, the user name will be in field 1 and the user ID will be in field 3.
c[$1]++; uids[$1]=uids[$1]" "$3
This counts the number of times that user name $1 occurs and saves the count in array c. It also saves the user ID, $3, associated with each name in array uids.
END{for (name in c) if (c[name]>1) printf "Duplicate User Name (%s):%s\n",name, uids[name]}
After we have finished processing getent's output, this looks for user names for which the count is greater than 1 and prints the info.
Multiline version of suggested code
getent passwd | awk -F: '
{
c[$1]++
uids[$1] = uids[$1] " " $3
}
END{
for (name in c)
if (c[name]>1)
printf "Duplicate User Name (%s):%s\n", name, uids[name]
}'

Shell Script- each unique user

I have a homework assignment: "for each unique user, report which group they are a member of and when they last logged in"
So far I have:
#!/bin/sh
echo "Your initial login:"
who | cut -d' ' -f1 | sort | uniq
echo "Now is logged:"
whoami
echo "Group ID:"
id -G $whoami
case $1 in
"-l") last -Fn 10 | tr -s " " ;;
*) last -Fn 10 | tr -s " " | egrep -v '(^reboot)|(^$)|(^wtmp a)|(^ftp)' | cut -d" " -f1,5,7 | sort -uM | uniq -c
esac
My question is: how I can show the each unique user? The script above only show the more recent user logged in the system, but I need all unique users.
Can anyone help?
Script using last
#!/bin/bash
while read user; do
echo "User '$user':"
echo -e "\t Last login: $(last -1R "$user" | awk 'NR==1{if($0 ~ /^$/){print "Never"}else{$1=$2="";print}}')"
echo -e "\t Groups: $(getent group | awk -F: -v user="$user" '$0 ~ user{a[i++]=$1} END{for(item in a)printf("%s ", a[item])}')"
done < <(getent passwd | awk -F: '{print $1}')
Output
Names have been changed to protect the innocent
User 'foo':
Last login: Oct 19 15:07:19 -0700 2010
Groups: foo groupA groupB
User 'bar':
Last login: Nov 16 11:40:23 -0800 2008
Groups: bar groupA groupC groupD
User 'baz':
Last login: Never
Groups: baz groupA groupD
The following link has some alternate ways of listing users. They involve reading /etc/passwd.
http://www.linuxquestions.org/linux/answers/Networking/How_to_list_all_your_USERs
There seems to be no other way than reading /etc/passwd, for example:
$ for u in `cat /etc/passwd | cut -d: -f1`; do echo $u `id -Gn $u`; done
To loop through any unique user you could get the content of the passwd file and get the first token of each line.
I'd suggest using getent passwd to read passwd, since /etc/passwd only contains users from local machine files (eg: no users from LDAP or other PAM plugins).
getent passwd | cut -d':' -f1
This command will return one user per line.
Then last and id will tell you their last login and their group:
for user in `getent passwd | cut -d':' -f1`
do
id ...
last ...
done

Resources