Command to merge linewise from 2 files
Hi..Everybody,
I am newbie in shell script, I want to know when the user password will expire. for that I made a small shell script like below Quote:
Quote:
Quote:
|
First things first. We have GOT to fix up what you already have.
Code:
users=$(grep /home /etc/passwd | grep -i "sh" | cut -d: -f 1 >> users.txt) 1) It unnecessarily uses multiple tools to do what one instance of the proper tool can do. awk is designed precisely for doing this kind of job. 2) You're sending all the output of the commands into users.txt, which means that the users variable gets nothing. 3) Even if we fix #2, multiple outputs should not be stored in a single variable. This is a job for an array. Code:
users=( $( awk -F':' '/\/home.*sh/ { print $1 }' /etc/passwd ) ) Code:
expire_date=$(grep /home /etc/passwd | grep -i "sh" | cut -d: -f 1 | while read user; do chage -l $user | sed -n '/Last/,+2p' | grep -v Last | grep -v inactive | cut -d: -f 2 >> expire.txt; done) Anyway, if you have the user list properly stored in an array, then it becomes trivial to get the date you want. Code:
for i in "${!users[@]}"; do Now you have matching array indexes for name and date, and can easily echo them to text files individually or as a whole. Code:
for i in "${!users[@]}" ; do Check out the BashGuide for a good intro to scripting. You'll want to read the section on arrays in particular: http://mywiki.wooledge.org/BashGuide |
You could do both in one pass,
Code:
while read user; do echo "user: $user, expires: $(chage -l $user | sed -rn '2 s/^.*: (.*)$/\1/p')"; done< <(sed -rn 's/^([^:]*):.*$/\1/gp' /etc/passwd) Code:
< <(sed -rn 's/^([^:]*):.*$/\1/gp' /etc/passwd) Each while...loop round reads one name, and echoes the name followed by a command substitution where 1) chage -l is called and 2) sed filters the last part after the : on the second line (the "expires" line). Aka: no need for intermediate files. |
know the user's expiration date
Quote:
Quote:
Hope you definitely help me in this. once again thank you very much master. |
Glad to help out.
Please use [code][/code] tags around your code, to preserve formatting and to improve readability. Do NOT use quote tags, which don't protect whitespace. Your new requirement is a bit more of a challenge, but not too hard, as long as you have the gnu version of date (standard on almost all Linux distros*). With it, you can convert the dates to epoch format (seconds passed since Jan 1, 1970). This allows you to do simple numeric comparisons between different times. Code:
now=$( date +%s ) By the way, to convert an epoch number back to another format, you have to prefix it with "@" Code:
datestring='1322159922' *The date implementations on other unixes generally don't have -d, so if you aren't on Linux you'll probably have to find some other tool for converting arbitrary dates, such as perl. |
Try this command
Code:
$paste users.txt expire.txt > merged.txt |
Code:
while read user; do echo "user: $user, expires: $(chage -l $user | sed -rn '2 s/^.*: (.*)$/\1/p')"; done< <(sed -rn 's/^([^:]*):.*$/\1/gp' /etc/passwd) Code:
#!/bin/bash Code:
bash pe Code:
chage -l roopa | sed -rn '2 s/^.*: (.*)$/\1/p' Code:
sed -rn 's/^([^:]*):.*$/\1/gp' /etc/passwd sed -rn '2 s/^.*: (.*)$/\1/p' sed -rn 's/^([^:]*):.*$/\1/gp' /etc/passwd Or could you please send me some url links by which I can be also like you in shell scripts. |
get mail about password expiration
H..David master.
Sorry for the late response. I could not see your kind reply since I was at out of station. Please excuse me. I am spoiling your valuable time with this thread. You are really genius. Code:
bash pass_expire Code:
date Code:
chage -l user2 Code:
Hi.(related username) kumar=kumar@domain.com roopa=roopa@domain.com user1=user@domain.com user2=user@domain.com Now the user1 and user2 is having the same mail ID i.e user@domain.com. Now the user@domain.com should get mail to change only for user2 account. This is my last question in this thread. I hope you definitely help me in this. |
This may be the first time I've ever been called a "genius". :hattip: But everything posted so far is well-understood by anyone with a reasonable amount of scripting experience. You'll get there too, eventually.
sed, grep and many other commands use regular expressions to parse out sections of text. There are many good tutorials available both online and in printed form. Just find one that looks good to you and study it until you at least understand the basic techniques, such as the lines juako gave. You'll be glad you did. As for mailing out the results, it's certainly not hard to do. But I'd probably set it up as a separate mail script that launches the first, or at least reads the output file from it, and sends the messages out based on that. Then just set cron to launch that script once per day. I'm not too familiar with cli mail programs though, so you'll have to figure out the exact commands yourself. Post what you come up with here and we'll be glad to look it over and give advice. |
1 Attachment(s)
Hi..David master, Thanks for your kind reply.
Before adding body message. Code:
bash pass_expire |
Well, as I said, I don't know much about how mail works, so I don't really know what you need to do to get it to send the right things to the right people.
I'm also not sure what you mean by sending messages to both "helpdesk and related". It's not clear to me who is "helpdesk" and who is "related". Could you elaborate please? The $USER variable is preset by the shell to the name of the user who owns the shell. In this case it's the name of the user running the script, and the value is expanded before the message is sent. You need to use the ${users[i]} array value for the name you want to supply to the message. But then again you should know that, as you're already doing it on the first line. In any case I think the script would be cleaner, and the text more easily modifiable, if you used a variable or function to supply the default message. A function would probably be the most flexible: Code:
|
1 Attachment(s)
Hi.. David master, Thanks for your kind reply.
You are helping me a lot. Thank you very much. Please excuse me, if you could not understand from my explanation. You are already near to that what I am expecting. I don't want you to confuse with helpdesk members, and you just leave it. Here I will tell clearly. The related users are nothing but the mail IDs for the user accounts from the passwd file, and those mail IDs for the user accounts as below. For example Code:
roopa=roopa@domain.com Code:
Password for roopa will expire in 2 days. Now if I add as only "mail -s "password expire" "$users" the related mail IDs are not getting mail. Some mail ID will get mails only then, when system user account and webmail account both are same and only if I add as Code:
mail -s "password expire" "${users[i]}@domainname I can also get mail if I add like below admins=mymailID@domain.com "mail -s "password expire" "$admins" "${users[i]}@domainname" Please find the attachment, I have removed also "$admins" because again I don't want you to get confuse with $admins and $users. It is enough, if the related mail IDs are getting mails about related accounts. I hope, now you are not confused and help me in this. |
I'm still not completely sure I follow you.
I think I see your main issue now though. If "users" is defined as an array, then "$users" is the same as "${users[0]}". So you're sending everything to the same address. If you want the full array list, you need to use "${users[@]}". Unless of course you want to send it to that user only, in which case use "${users[i]}". For the second part, are you saying that some users have to have their messages sent to different addresses from the default? If so, we'd have to use some kind of a test to compare the username to a preset list, and send the message to a different address if there's a match. Assuming you're using bash 4+, an associative array would probably be the best option. Code:
#define a list of exceptions to the default mail addresses Code:
### external file (exceptions.txt) ### Code:
if [[ "${!xpns[*]}" =~ "${users[i]}" ]]; then It's even possible to shorten the full if test to this: Code:
address="${xpns[${users[i]}]:-${users[i]}}" |
All times are GMT -5. The time now is 11:06 PM. |