LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Server (http://www.linuxquestions.org/questions/linux-server-73/)
-   -   crontab which is written once and runs for everyone (http://www.linuxquestions.org/questions/linux-server-73/crontab-which-is-written-once-and-runs-for-everyone-754123/)

Hi_This_is_Dev 09-10-2009 06:03 AM

crontab which is written once and runs for everyone
 
Hi,


I want to run a certain process every minute during 2200 to 2400 hours. For that purpose I am scheduling the job using crontab as detailed below:


giving this command:

Code:

[root@localhost ~]# crontab -e
Adding this entry:

Code:

*/1    22-23  *      *      *      /usr/bin/free

Now I want this info/output to be emailed to every user in the network.

If I specify a particular user then it is working. How to configure the crontab which can work for all the users in the network?


Thanks!

ddaemonunics 09-10-2009 07:28 AM

you can pipe the output to some mail program

command | mail -s "Subject of mail" user1@domain user2@domain user3@domain

Hi_This_is_Dev 09-10-2009 02:26 PM

Well, thanks for the info! I was trying that method when I was posting the question. I was looking for some other better way.... running a script which can list all the users and then substitute them one by one for the mail program to use in the "to or cc" field.

Well, one more thing. The method which you have stated is fine if we want to email the output of a single command such as given in this fragment:

Code:

/bin/ps | mail -s "Process Info" userX userY userZ userN

but we have to use the same long line of the users for every command. So, is there any workaround for it?


One more thing yet: the commnad as given below:

Code:

crontab -u userName -e
can configure crontab for that particular user only. How do we do it if we want to configure the same crontab for all the users in our network?

chrism01 09-11-2009 12:43 AM

AIUI, free http://linux.die.net/man/1/free only applies to the whole system, not each user, so there's no point sending it to everyone, and especially not every minute(!)
You could post it to an Intranet website.
Alternatively you can mail it to a mailing list address, which contains the address of all users.

Hi_This_is_Dev 09-11-2009 07:10 AM

Well, that was just an example. I would not want to do that every minute! ;)

However, your idea: "Alternatively you can mail it to a mailing list address, which contains the address of all users." sounds good and I will try it and post my findings here.

Quote:

Originally Posted by chrism01 (Post 3678245)
AIUI, free http://linux.die.net/man/1/free only applies to the whole system, not each user, so there's no point sending it to everyone, and especially not every minute(!)
You could post it to an Intranet website.
Alternatively you can mail it to a mailing list address, which contains the address of all users.


colucix 09-11-2009 07:33 AM

Quote:

Originally Posted by Hi_This_is_Dev (Post 3677739)
but we have to use the same long line of the users for every command. So, is there any workaround for it?

Yes. You can put multiple commands in a subshell and pipe the output to the mail command:
Code:

(
  date
  free
  echo
  $(cat logfile)
  echo
  echo Greetings\!
) | /usr/sbin/sendmail etc etc...

Quote:

How do we do it if we want to configure the same crontab for all the users in our network?
Write the content of the crontab in a file and pass the file name as argument to the crontab command (beware it will overwrite any existing user's crontab):
Code:

for user in $users
do
  crontab -u $user file
done

If users are spread over diffrent machines in the local network and you have to use ssh to accomplish the task, you can use process substitution in place of the file, with the same result:
Code:

for user in $users
do
  ssh -n root@${host} "crontab -u ${user} <(echo '0 9 * * * /bin/date')"
done

Anyway, I second the suggestion by chrism01: run the commands and send the output to your local mailing list. Far more easy to mantain. Furthermore, users can always delete or edit their own crontab and your effort is lost.

Hi_This_is_Dev 09-13-2009 03:08 PM

Storing Returned Lines of Values in an Array
 
Thanks for the useful methods you have devised!

Well, to complete this thread/post, I want to create that array "users" which can hold the names of the users found in the /etc/passwd file.

Have a look at this command:
Code:

grep home /etc/passwd | cut -d: -f1
It returns the names of the users on seperate lines.

I have tried to store those names in an array but in vain. I tried awk also but it didn't seem to work.


For example, this one works fine:

Code:

freearray=( $(free|awk '/Swap/ {print $2,$3,$4}') )

echo "${freearray[0]}


Any ideas?

colucix 09-13-2009 03:17 PM

Strange. Both of these work for me:
Code:

array=($(grep /home/ /etc/passwd | cut -d: -f1))
array=($(awk -F: '/\/home\//{print $1}' /etc/passwd))

I just added surrounding slashes to the pattern, but it should not make the difference.

Edit: I forgot to mention that if the array approach does not work, you can always pass the output directly to a for or while loop. For example:
Code:

for user in $(awk -F: '/\/home\//{print $1}' /etc/passwd)
do
  echo $user
done

while read user
do
  echo $user
done < <(awk -F: '/\/home\//{print $1}' /etc/passwd)


Hi_This_is_Dev 09-13-2009 03:38 PM

Thanks!!! Muchas Gracias!!!


Both of them work! No, surrounding slashes don't make any differences in the presented case:

Code:

-bash-2.05b# array=($(grep /home/ /etc/passwd | cut -d: -f1))

-bash-2.05b# echo "${array[0]}"
x
-bash-2.05b# echo "${array[1]}"
student

-bash-2.05b# echo "${array[3]}"
dev

...

-bash-2.05b# array=($(grep home /etc/passwd | cut -d: -f1))

-bash-2.05b# echo "${array[3]}"
dev

...


Well, I want to know why are we using a $ here:

Code:

array=($(grep home /etc/passwd | cut -d: -f1))
Nope, without it the command won't run.

colucix 09-13-2009 03:50 PM

Quote:

Originally Posted by Hi_This_is_Dev (Post 3681390)
Thanks!!! Muchas Gracias!!!

You're welcome! :)
Quote:

Originally Posted by Hi_This_is_Dev (Post 3681390)
Well, I want to know why are we using a $ here:

Code:

array=($(grep home /etc/passwd | cut -d: -f1))
Nope, without it the command won't run.

It is the bash syntax for command substitution:
Code:

$(command)
which equals the original /bin/sh syntax which uses back-ticks, but with some additional feature, like the ability to use nested commands. A complete explanation in the Advanced Bash Scripting Guide, here.

Hi_This_is_Dev 09-13-2009 03:59 PM

This is great:

Code:

while read user
        do
                echo "Hello, "$user"!"
        done < <(awk -F: '/\/home\//{print $1}' /etc/passwd)

If we exclude the last line and put in a script file only:

Code:

while read user
        do
                echo "Hello, "$user"!"
        done

then it waits for an input and echos it back on the console. However, we must stop the process as it is an indefinite loop.

Your "for" lopp construct is pretty much straightforward and I need no explanation.

I think in the "while" loop the value is beaing "read" from the output of the command fragment that follows "done".

Hi_This_is_Dev 09-13-2009 04:15 PM

Thanks for explaining me the following command:

$() as in:

Code:

echo $(date)


By the way, I am at work in the company I work for. What do you do? My present work involves monitoring of networks, backups, domino servers, etc. as I am in Data Center Operations.

colucix 09-13-2009 04:16 PM

Quote:

Originally Posted by Hi_This_is_Dev (Post 3681415)
I think in the "while" loop the value is beaing "read" from the output of the command fragment that follows "done".

Yes. The line:
Code:

done < <(awk -F: '/\/home\//{print $1}' /etc/passwd)
is made of two parts. The first < sign is the usual redirection of standard input: instead of accepting input from the keyboard, the loop (and its read statement in this specific case) accepts input from what follows. The rest of the line uses process substitution, with the syntax:
Code:

<(command)
again the Advanced Bash Scripting Guide comes in help, here. A loop of this kind has the great advantage it can easily manage input containing blank spaces, provided you enclose the value of the loop variable in double quotes, when using it inside the loop itself. For example suppose you have two files (one of them with spaces in its name):
Code:

$ ls -l *.txt
-rw-r--r-- 1 alex users 0 2009-09-13 23:11 file.txt
-rw-r--r-- 1 alex users 0 2009-09-13 23:11 file with spaces.txt
$ for file in $(ls *.txt)
> do
>  ls -l "$file"
> done
-rw-r--r-- 1 alex users 0 2009-09-13 23:11 file.txt
ls: cannot access file: No such file or directory
ls: cannot access with: No such file or directory
ls: cannot access spaces.txt: No such file or directory
$ while read file
> do
>  ls -l "$file"
> done < <(ls *.txt)
-rw-r--r-- 1 alex users 0 2009-09-13 23:11 file.txt
-rw-r--r-- 1 alex users 0 2009-09-13 23:11 file with spaces.txt

As you can see the for loop fails, whereas the while loop with process substitution do its job without a glitch.

colucix 09-13-2009 04:20 PM

Quote:

Originally Posted by Hi_This_is_Dev (Post 3681425)
By the way, I am at work in the company I work for. What do you do? My present work involves monitoring of networks, backups, domino servers, etc. as I am in Data Center Operations.

I'm not at work, now (here in Italy is almost midnight). By the way, I'm a physical and biological oceanographer.

Hi_This_is_Dev 09-13-2009 05:22 PM

Quote:

Originally Posted by colucix (Post 3681435)
I'm not at work, now (here in Italy is almost midnight). By the way, I'm a physical and biological oceanographer.



That's why you are a guru! ;) I have obsereved that you are very generous when it comes to sharing knowledge. Grazie! :)

It's 4 am here in New Delhi (India). We have a site in Milan too. Buona notte!


All times are GMT -5. The time now is 02:42 PM.