How to get the list of 60Days old users in Perforce - perforce

I need to return records where there is an access date older than 60 days along with Perforce UserName, Email & Last Accessed Date in Perforce. I am aware of the perforce command to get the all user list with "%User% %Email% %Access%" in combination with p4 users. However, I'm looking for some script that can be set in a cron job to daily monitor and send the alert through email.
The command that i am using to get all user list is
p4 -ztag -F "%User% %Email% %Access%" users | awk '{$3=strftime("%Y/%m/%d %H:%M:%S",$3)} {print}' | sort -k 2,3 | sed 's/[ \t]/,/g'
Any help would be much appreciated.

On Linux, this'll generate a CSV-style list sorted by username:
p4 -ztag -F "%User% %Email% %Access%" users | awk '$3 < '"$(date -d "60 days ago" +%s)"' {print $1","$2","strftime("%Y/%m/%d %H:%M:%S",$3)}'
If you want to also sort by Access date, you could sort before awk.
p4 -ztag -F "%User% %Email% %Access%" users | sort -k3rn | awk '$3 < '"$(date -d "60 days ago" +%s)"' {print $1","$2","strftime("%Y/%m/%d %H:%M:%S",$3)}'
For OSX, this would look like:
p4 -ztag -F "%User% %Email% %Access%" users | sort -k3rn | awk '$3 < '"$(date -v-60d +%s)"' {print $1","$2","strftime("%Y/%m/%d %H:%M:%S",$3)}'
If you're redirecting any of the above commands to a text file, you could then read said text file back in as a list of users to then delete.
awk -F, '{print $1}' old.users.list | xargs -I{} p4 user -df {}
Note this is a fairly shallow way of doing it. It won't remove their workspaces or pending changelists/shelves. It's possible to incorporate those steps as part of a more thorough cleanup script but various companies have their own policies about what to do with shelved changes, etc.
You will at least be able to quickly free up a license this way.

In Python, using the p4python module:
from datetime import datetime
from P4 import P4
with P4().connect() as p4:
for user in p4.run_users():
access_time = datetime.fromtimestamp(int(user['Access']))
if (datetime.now() - access_time).days > 60:
print(user['User'], user['Email'])
# or do whatever else you want

Related

How would I disable accounts that have been inactive for 90 days in Linux?

Working on a script that disables accounts that have been inactive for 90 days. Couldn't really find an answer after researching my problem for a few days, but I did find this command on a forum:
lastlog -t 10000 > temp1; lastlog -t 90 > temp2; diff temp1 temp2; rm temp1; rm temp2
This command outputs the users that have been inactive for 90 days. I think the solution to my problem would be to:
Filter the output of this command so only the usernames are displayed (in a list, with 1 username per line).
Take this output and write it to a text file.
Run a for-loop that for each line in the file, the contents of the line (which should be just a single username) are stored in a variable called "inactiveUser". Then the command usermod -L $inactiveUser will be executed.
Would my proposed solution work? If so, how could it be achieved? Is there a much easier method to lock inactive accounts that I am not aware of?
you can simplify this with:
lastlog -b 90
which directly lists users who have not logged in in the past 90 days.
however, it also has a header row, and lists lots of system users.
use tail to skip the header row:
lastlog -b 90 | tail -n+2
then you could use grep to filter out system users:
lastlog -b 90 | tail -n+2 | grep -v 'Never log'
although perhaps there is a safer way to find real, non-system users, e.g.:
cd /home; find * -maxdepth 0 -type d
that issue aside, you can get just the usernames out with awk:
lastlog -b 90 | tail -n+2 | grep -v 'Never log' | awk '{print $1}'
then either output the list to a file, or else directly run usermod via while read loop or xargs:
lastlog -b 90 | tail -n+2 | grep -v 'Never log' | awk '{print $1}' |
xargs -I{} usermod -L {}
perhaps you should also log what you've done:
lastlog -b 90 | tail -n+2 | grep -v 'Never log' | awk '{print $1}' |
tee -a ~/usermod-L.log | xargs -I{} usermod -L {}
While the other answer works, it can be made much cleaner by using awk instead of tail | grep | awk
lastlog -b 90 | awk '!/Never log/ {if (NR > 1) print $1}' | xargs -I{} usermod -L {}
The awk command checkes for lines that don't have the expression 'Never log' in it (!/Never log/).
NR > 1 emulates tail -n +2.
print $1 prints the first column.

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.

How can we get list of non-system users on linux?

Considering that all users with id >= 1000 are non-system users, how can we get list of these users in a single command?
You need to get all users whose gid is greater than or equals 1000. Use this command for that:
awk -F: '($3>=1000)&&($1!="nobody"){print $1}' /etc/passwd
If you want system users (gid<1000) it will be:
awk -F: '($3<1000){print $1}' /etc/passwd
You can use awk for this task:
awk -F: '$3 >= 1000' /etc/passwd
This will split the /etc/passwd file by colon, then if field 3 (userid) is greater than or equal to 1000, it will print the entire /etc/passwd record.
If you want to get only the username out of this list then:
awk -F: '$3 >= 1000 {print $1}' /etc/passwd
Where $1 is the first field of etc/passwd which is the username.
Supposing that the system recognizes only local users (i.e. those recorded in /etc/passwd, as opposed to any authenticated via a remote service such as LDAP, NIS, or Winbind), you can use grep, sed, or awk to extract the data from /etc/passwd. awk is the most flexible of those, but how about a solution with sed:
sed -n '/^\([^:]\+\):[^:]\+:[1-9][0-9]\{3\}/ { s/:.*//; p }' /etc/passwd
System users (should be) those listed in /etc/passwd with UIDs less than 1000. The actual number is a convention only. Non-system users need not be listed there. You can get the list using getent and awk ignoring "nobody" (also a convention):
getent passwd |awk -F : '$3 >= 1000 && $3 < 65534'
Here's an answer for doing this on all your machines, using Ansible and awk, building on JNevill's answer:
ansible -i inventories/cd_staging all -m shell -a "awk -F: '\$3 >= 1000 && \$7 \!~ /nologin/ {print \$1}' \/etc\/passwd |sort"
You'll want to ignore GIDs less than 1000, but also GIDs greater than 60000. Ubuntu/Debian reserve these for various system services.
awk -F: '($3>=1000)&&($3<60000)&&($1!="nobody"){print $1}' /etc/passwd

Display users on Linux with tabbed output

I am working with Linux and I am trying to display and count the users on the system. I am currently using who -q, which gives me a count and the users but I am trying not to list one person more than once with it. At the same time I would like the output of users on separate lines as well or tabbed better than it currently is.
The following will show the number of unique users logged in, ignoring the number of times they are each logged in individually:
who | awk '{ print $1; }' | sort -u | awk '{print $1; u++} END{ print "users: " u}'
If the output of who | awk '{ print $1 }' is :
joe
bunty
will
sally
will
bunty
Then the one-liner will output:
bunty
joe
sally
will
users: 4
Previous answers have involved uniq (but this command only removes duplicates if they are storted, which who does not guarantee, hence we use sort -u to achieve the same.
The awk command at the end outputs the results whilst counting the number of unique users and outputtig this value at the end.
I think you want
who | awk '{print $1}' | uniq && who -q | grep "\# " | cut -d' ' -f2

In Perforce, how do I find the local path for files in a pending changelist?

Given a Perforce changelist number, I want to find the local path of all files in that pending changelist.
p4 describe changelist -- gets me the depot path for files in the changelist (method 1)
p4 opened -c changelist -- gets me the depot path for files in the changelist (method 2)
p4 have -- gets me the depot path and local path for all files that have previously been submitted
Using a combination of p4 describe and p4 have, I can find the local paths for all files in the changelist that have previously been submitted to Perforce (and are opened for delete or edit).
But what about files that are opened for add? p4 have does not know anything about files that are opened for add.
Given a pending Perforce changelist, how do I find the local path for files that are about to be added to Perforce?
To output the local path of all pending adds of a changelist you can use:
p4 opened -c changelist | grep -w add | sed 's/#.*//' \
| p4 -x - where | awk '/^\// {print $3}'
This does the same without grep but is a bit more obscure:
p4 opened -c changelist | sed -n 's/\(.*\)#.*- add .*/\1/p' \
| p4 -x - where | awk '/^\// {print $3}'
You could of course also use
p4 -ztag opened -c changelist
This will report both the depotFile and the clientFile for each opened file.
To list only client files:
p4 -ztag opened -c changelist | grep clientFile | awk '{print $3}'
Replacing //client/ with the client's root is left as an exercise for the reader.
Local path for all files in a pending changelist without any external or platform-specific tools:
p4 -F %clientFile% fstat -Ro -F action=add [-e CHANGE] //...
Remove the '-F action=add' if you want to get files opened for all actions.
p4 opened -s -c <changelist#> | awk -F " " '{print $1}' | p4 -x - where | awk -F " " '{print $3}'
Based on Peter G's answer, translated into powershell 2.0:
p4 opened -c changelist
| Where-Object{$_ -match "add"}
| ForEach-Object{p4 where ($_.split('#')[0])}
| ForEach-Object{$_.split()[2]}

Resources