Counting the same lines from output - linux

I want to list all shells with number of how many users have this shell set as default
to get example output like this :
13 /bin/bash
6 /sbin/nologin
1 /usr/sbin/nologin
the only command that I was managed to create is like this:
cut -d: -f1,7 /etc/passwd | grep -c bash
which returns me only the number of users with set bash as default
Can anyone tell me how should I modify this to get output as I mentioned before?

First, you only want column 7 from the passwd file. The usernames will just get in the way. Then sort and use the uniq command to count them:
$ cut -d: -f7 /etc/passwd | sort | uniq -c
2 /bin/bash
24 /bin/false
1 /bin/sync
1 /usr/local/bin/fish
16 /usr/sbin/nologin

Related

Why doesn't the pipeline take effect in bash in Linux?

Here is to count the number of sessions by the same login user.
I could run the direct command if I know the specific user name, such as usera, as the following:
who | grep usera | wc -l
And if I don't know the current user, I need to user parameter.
But the following codes don't work:
currentuser=`whoami`
sessionnumber=`who | grep "$currentuser" | wc -l`
What's the error?
Thanks!
Grep has the -c flag so the wc -l plus the additional pipe is not needed.
who | grep -c -- "$USER"
"$LOGNAME" is also an option instead of "$USER", which one is bash specific? I don't know, all I know is that they are both on Linux and FreeBSD system. The -- is just a habit just in case the user starts with a dash grep will not interpret it as an option.
sessionnumber=`who | grep "$currentuser" | wc -l`
You are assigning the result of the who | ... command to a variable and to see its value you can use echo $sessionnumber
Looks like you are confused about parameters and variables.
What you are trying to get is likely
who | grep $(whoami) | wc -l
The $() is equivalent to the backticks you used.
When you write
sessionnumber=``
this will run whatever is within the backticks and save the output to a variable. You can then access the variable using the dollar notation:
echo "$sessionnumber"

How to list all users in an administrative group in linux

i am using "getent passwd | cut -d : -f 1 | xargs groups > users.txt" but this lists all users and the groups they are in. In my case there are thousands of users I only need the list of users part of a specific group.
current output is in pic I don't need the members of linux_users group
Each record in /etc/group ends with a list of users that have that group as their supplementary group ( See http://linux.die.net/man/5/group ).
To get all members of your target group, you need to get those plus all users who have the target group as their primary group (in /etc/passwd, identified by your target group's number mentioned in /etc/group).
This script will get you both (you can call it group_ls or something like that):
#!/bin/sh
num_membs="$( getent group "$1" |cut -d: -f3,4 )"
num="${num_membs%:*}"; membs="${num_membs#*:}"
( IFS=,
printf '%s\n' $membs
awk -v num=$num -F: ' $4 == num { print $1 } ' /etc/passwd
) | sort -u
Alternatively, based on your approach
getent passwd | cut -d : -f 1 | xargs groups |
grep ":.* $1 .*" |cut -d : -f1
should do it too.
You can pipe to grep to narrow down the list that you get. Use some like grep groupname.
Grep: http://www.gnu.org/software/grep/manual/grep.html
Then you can use awk to only get part of a line.
Awk: http://tldp.org/LDP/abs/html/awk.html
So in your case you could do: getent passwd | cut -d : -f 1 | xargs groups | grep linux_admins | awk {'print $1'} > users.txt
You can also read the list of users associated with a group (example: users below) into an array in bash with the following:
IFS=$',\n' read -a names < <(grep '^users:' /etc/group | sed 's/^.*://')
Then you can access each user in a simple loop, e.g.
for i in ${names[#]}; do echo "$i"; done
This will only work for shells that support indexed arrays and process substitution, otherwise the pipe gymnastics are required.

list of logged in unique users in linux

I am working in linux environment as a non root user. I am using users command to get the logged in users
users
But it returns the user names multiple times because multiple shells are created with same login. Is there any way to print the unique user list using users commad.
Even i tried by
users | sort -u
Still it returns the user names multiple times.
Try with this -
who| awk '{print $1}'|sort -u
users | sort -u
Still it returns the user names multiple times.
Of course. sort is line based, and users only prints a single line.
What you want is to just look at the first word per line before sort -u in who output:
$ who|cut -f 1 -d " "|sort -u
barney
fred
wilma
or
$ who|sed 's/ .*//' |sort -u
barney
fred
wilma
However, if you are interested in some of the actual lines output by who you can also use
$ who|sort -u -k 1,1
barney pts/23 Aug 26 10:11 (:5.0)
fred pts/3 Jun 11 18:38 (:6.0)
wilma pts/0 Jul 31 07:29 (:3.0)
You can try this command: who | cut -d' ' -f1 | sort | uniq
You can use w command to get the list of logged in users and the details
This one is a bit shorter:
users | tr ' ' '\n' | sort -u

The number of processes a user is running using bash

I would like to know how I could get the number of processes for each user that is currently logged in.
You could try some variation of this:
ps haux Ou | cut '-d ' -f1 | uniq -c
It gives you the number of processes for each users (being logged in or not). Now you could filter those results using the output of the w command or another way of determining who is logged in.
Give this a try:
ps -u "$(echo $(w -h | cut -d ' ' -f1 | sort -u))" o user= | sort | uniq -c | sort -rn
In order to properly handle usernames that may be longer than eight characters, use users instead of w. The latter truncates usernames.
ps -u "$(echo $(printf '%s\n' $(users) | sort -u))" o user= | sort | uniq -c | sort -rn
ps -u aboelnour | awk 'END {print NR}'
will show number of process which user aboelnour running it
If you are ever concerned about nearing the user process limit shown by ulimit -a, the you want to get ALL the processes (including LWPs). In such a case you should use:
ps h -Led -o user | sort | uniq -c | sort -n
On one system doing this:
ps haux Ou | cut '-d ' -f1 | uniq -c
yields:
# ps haux Ou | cut '-d ' -f1 | uniq -c
30 user1
1 dbus
3 user2
1 ntp
1 nut
1 polkitd
2 postfix
124 root
2 serv-bu+
where doing the former yields the true process count:
# ps h -Led -o user | sort | uniq -c | sort -n
1 ntp
1 nut
2 dbus
2 postfix
2 serv-builder
3 user2
6 polkitd
141 root
444 user1
Just try:
lslogins -o USER,PROC
If you just want a count of processes you can use procfs directly like this:
(requires linux 2.2 or greater)
you can use wc:
number_of_processes=`echo /proc/[0-9]* | wc -w`
or do it in pure bash (no external commands) like this
procs=( /proc/[0-9]* )
number_of_proccesses=${#procs[*]}
If you only want the current userid
procs=( /proc/[0-9]*/fd/. )
number_of_proccesses=${#procs[*]}
userlist=$(w|awk 'BEGIN{ORS=","}NR>2{print $1}'|sed 's/,$//' )
ps -u "$userlist"
Following links contain useful ps commands options including your requirements:
Displaying all processes owned by a specific user
Show All Running Processes in Linux
Here is my solution, for Linux:
$ find /proc –user $USER -maxdepth 1 -name '[0-9]*' | wc –l
This solution will not fail when the number of processes is larger than the command line limit.

linux shell scripting kiddie's question

an Unix shell script with only purpose - count the number of running processes of qmail (could be anything else). Easy thing, but there must be some bug in code:
#!/bin/bash
rows=`ps aux | grep qmail | wc -l`
echo $rows
Because
echo $rows
always shows greater number of rows (11) than if I just count rows in
ps aux | grep qmail
There are just 8 rows. Does it work this way on your system too?
Nowadays with linux, there is pgrep. If you have it on your system, you can skip grep -v grep
$ var=$(pgrep bash) # or `pgrep bash | wc -l`
$ echo $var
2110 2127 2144 2161 2178 2195 2212 2229
$ set -- $var; echo ${#}
8
also, if your ps command has -C option, another way
$ ps -C bash -o pid= | wc -l
if not, you can set a character class in your grep pattern
$ ps aux|grep [q]mail | wc -l
It appears that you're counting the grep process itself and the header line that ps normally prints before its output.
I'd suggest something more like:
qprocs=$(ps auxwww | grep -c "[q]mail")
... note that GNU grep has a "-c" switch to have it print a "count" of matches rather than the lines themselves. The trick with the regular expression here is to match qmail without matching the literal string that's on the grep command line. So we take any single character in the string and wrap it in square brackets such that it is a single character "class." The regexp: [q]mail matches the string qmail without matching the string [q]mail.
Note that even with this regex you may still find some false positive matches. If you really want to be more precise then you should supply a custom output format string to your ps command (see the man pages) or you should feed it through a pipemill or you should parse the output of the ps command based on fields (using awk or cut or a while read loop). (The -o option to ps is by far the easiest among these).
No, since I'm not running qmail. However, you will want to, at a bare minimum, exclude the process running your grep:
ps aux | grep qmail | grep -v grep
For debugging, you may want to do:
rows=`ps aux | grep qmail`
echo $rows >debug.input
od -xcb debug.input
(to see your input to the script in great detail) and then rewrite your script temporarily as:
#!/bin/bash
rows=`cat debug.input | wc -l`
echo $rows
That way, you can see the input and figure out what effect it's having on your code, even as you debug it.
A good debugger will eventually learn to only change one variable at a time. If your changing your code to get it working, that's the variable - don't let the input to your code change as well.
Use
$ /sbin/pidof qmail
A few ways...
ps -e | grep ' [q]mail' | wc -l
ps -C qmail -opid= | wc -l
pidof qmail | tr ' ' '\n' | wc -l
pgrep is on many Linux distributions, and I imagine available for other Unices.
[dan#khorium ~]$ whatis pgrep
pgrep (1) - look up or signal processes based on name and other attributes
[dan#khorium ~]$ pgrep mingetty
1920
1921
1922
1923
1924
In your case, pgrep qmail | wc -l should do the trick.

Resources