Thursday, January 31, 2008

cygwin cron on Win2K/XP

Well, setting up Cygwin (http://www.cygwin.com/) cron on Win2K Server and my XP workstation is a complete bitch. Simply put, my scripts would not start properly. I used the latest version of the Cygwin DLL, v.1.5.25-7.

Why?
In a nutshell, my problems came down to three issues:
1) cron would only work as my local domain account
-lots of good information here: http://www.andrewlouie.com/wordpress/?page_id=88
-and a little bit of info here: http://cygwin.com/cygwin-ug-net/ntsec.html#ntsec-switch
2) cron needed to be installed using "smbntsec" privileges for my SSH-based scripts to work
3) finally, c:\cygwin\bin needed to be the last entry in my PATH enviroment variable

Installation Steps Added 3/1/2008
Most of the following information comes from these gentlemens' fine posts:
-http://cygwin.com/cygwin-ug-net/ntsec.html#ntsec-switch
-http://ist.uwaterloo.ca/~kscully/CygwinSSHD_W2K3.html

The overview is that you'll have to do quite a bit to get cron under cygwin running properly. Please refer to the two docs above, but here is the short list of steps:
1) decide on a user that cron will run under
- we have a domain account used for scheduled tasks, so I used that
2) add the user to /etc/passwd
- setup a proper home directory in /etc/passwd
- if you do not have a proper home directory, you'll see "Can't cd to $HOME" errors from the output of cronevents.exe
- copy valid .bashrc/.bash_profile files to your users' home directory
3) under Control Panel -> Administrative Tools -> Local Security Policy -> Local Policies -> User Rights Assignment -> tweak your Win2K/XP Local Security Policy settings to add the chosen user to
- (Adjust Memory Quotas for a Process) Increase Quotas
- Create a Token Object
- Log on As A Service
- Replace Process Level Token
4) create a crontab for your user
- crontab -e
5) verify that the permissions on the command(s) to be cron'd will allow the user you've chosen to execute the command(s)
6) run cron-config to enable the cron daemon
- you may get execute and write errors related to permissions on /var, /var/run, /var/log, /usr/sbin/sendmail, /usr/bin/cronlog. I took the easy route and fixed them with:
chmod 766 [file or directory]
or
chmod 755 [file or directory]

Also, make sure the user that you will be using to execute cron jobs is setup in /etc/passwd.

6) once the cron daemon is running, validate that your script is running properly by looking at cronevents.exe and $HOME/cron.log
- if you have not applied the Local Policy settings correctly, you may see the "can't switch user context" error in the log output
- at one point, I received this error:
C:\cygwin\usr\sbin\cron.exe: *** fatal error - could not load user32, Win32 error 1114

I resolved this by moving my user from the "guest" group to the "Administrators" group in /etc/passwd. Of course, you may not want to do this based on your security needs.

troubleshooting
I learned a few things along the way:
1) after installing the cron package into Cygwin, you want to use cron-config to setup cron
2) after enabling your cron, cronevents.exe is a good thing
3) occasionally, $HOME/cron.log provides some useful info
4) the CYGWIN environment variable can be a nasty beast:
http://www.cygwin.com/cygwin-ug-net/using-cygwinenv.html
5) the HOME environment variable must be set properly:
http://blog.spikesource.com/crontab.htm suggests running "env" in your cron out to a file to find differences between your user environment and the cron environment. Good idea!
6) don't forget your scripting basics:
/2007/07/why-doesnt-my-shell-script-run-under.html
7) documentation can help:
C:\cygwin\usr\share\doc\Cygwin\cron-4.1-6.README

Detail
1) after you install the cron packages from the CygWin setup program, make sure to use "cron-config" to add or remove the cron daemon as an NT service, and perform configuration of cron.

I needed to run the service as myself, with the security tweaks described in both these places:
-http://cygwin.com/cygwin-ug-net/ntsec.html#ntsec-switch
-http://www.andrewlouie.com/wordpress/?page_id=88

Here's a sample of the installer dialog:
$ cron-config
Cron is already installed as a service under account DOMAIN\USER.
Do you want to remove or reinstall it? (yes/no) yes
OK. The cron service was removed.

Do you want to install the cron daemon as a service? (yes/no) yes
Enter the value of CYGWIN for the daemon: [ntsec smbntsec] smbntsec

The service can run either as yourself or under a privileged account.
Running as yourself allows better access to network drives,
but does not allow to run the crontab of other users.
Do you want to the cron daemon to run as yourself? (yes/no) yes

Please enter the password for user 'SODO':
Reenter:
Running cron_diagnose ...
... no problem found.

Do you want to start the cron daemon as a service now? (yes/no) yes
OK. The cron daemon is now running.

In case of problem, examine the log file for cron,
/var/log/cron.log, and the Windows event log (using /usr/bin/cronevents)
for information about the problem cron is having.

Examine also any cron.log file in the HOME directory
(or the file specified in MAILTO) and cron related files in /tmp.

If you cannot fix the problem, then report it to cygwin@cygwin.com.
Please run the script /usr/bin/cronbug and ATTACH its output
(the file cronbug.txt) to your e-mail.


Occasionally, cron-config may bark at you for permissions errors on /etc/group and /etc/passwd. Fix them and then re-run cron-config.

Event Log Errors
If I ran the cron daemon under the SYSTEM user context, I got the following Application Event log error:
The description for Event ID ( 0 ) in Source ( /usr/sbin/cron ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: /usr/sbin/cron: PID 5300: (CRON) error (can't cd to HOME).

After a proper install, I still see a running set of Information Alerts in the Application logs. These don't seem to hurt, as my jobs still runs:
The description for Event ID ( 0 ) in Source ( /usr/sbin/cron ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: /usr/sbin/cron: PID 5016: (SODO) CMD (/scheduledtasks/scripts/load.sh ).

2) Setup your cron using "crontab -e". This puts you into the edit window of the text editor that you installed with Cygwin.

Once a cron is setup, view the output of cronevents.exe to see what cron jobs executed:
$ cronevents.exe tail
2008/01/31 16:53:01 [SODO] /usr/sbin/cron: PID 5992: (SODO) CMD (/scripts/load.sh >> /scripts/load.txt )
2008/01/31 16:53:01 [SODO] /usr/sbin/cron: PID 6652: (SODO) CMD (/scripts/connScript.sh >> /scripts/conn.txt)
2008/01/31 16:54:01 [SODO] /usr/sbin/cron: PID 8132: (SODO) CMD (/scripts/load.sh >> /scripts/load.txt )
2008/01/31 16:54:01 [SODO] /usr/sbin/cron: PID 4708: (SODO) CMD (/scripts/connScript.sh >> /scripts/conn.txt)
2008/01/31 16:55:01 [SODO] /usr/sbin/cron: PID 8164: (SODO) CMD (/scripts/connDiff.sh)
2008/01/31 16:55:01 [SODO] /usr/sbin/cron: PID 3372: (SODO) CMD (/scripts/connAlert.sh )
2008/01/31 16:55:01 [SODO] /usr/sbin/cron: PID 4460: (SODO) CMD (/scripts/load.sh >> /scripts/load.txt )
2008/01/31 16:55:01 [SODO] /usr/sbin/cron: PID 7976: (SODO) CMD (/scripts/connScript.sh >> /scripts/conn.txt)
2008/01/31 16:56:01 [SODO] /usr/sbin/cron: PID 6424: (SODO) CMD (/scripts/load.sh >> /scripts/load.txt )
2008/01/31 16:56:01 [SODO] /usr/sbin/cron: PID 2676: (SODO) CMD (/scripts/connScript.sh >> /scripts/conn.txt)


3) Viewing the cron logs are important! The cron.log is place in $HOME/cron.log:
$ cat /cygdrive/h/cron.logThis file was written by the /usr/bin/cronlog script on 20080131_165003
From: root (Cron Daemon)To: SODOSubject: Cron
SODO@SODO02 /scripts/connDiff.sh

X-Cron-Env: ALLUSERSPROFILE=C:\Documents and Settings\All Users
X-Cron-Env: COMMONPROGRAMFILES=C:\Program Files\Common Files
X-Cron-Env: COMPUTERNAME=SODO02X-Cron-Env: COMSPEC=C:\WINDOWS\system32\cmd.exe
X-Cron-Env: CYGWIN=smbntsecX-Cron-Env: NUMBER_OF_PROCESSORS=4
X-Cron-Env: OS=Windows_NTX-Cron-Env: PATH=/cygdrive/c/Program Files/PHP/:/cygdrive/c/oracle9i/bin:/cygdrive/c/oracle9i/jre/1.4.2/bin/client:/cygdrive/c/oracle9i/jre/1.4.2/bin:/cygdrive/c/Program Files/Oracle/jre/1.1.8/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/TeaLeaf:/cygdrive/c/Program Files/Python25:/cygdrive/c/Program Files/QuickTime/QTSystem/:"C:/Program Files/Symantec/Norton Ghost 2003/":/cygdrive/c/Program Files/Common Files/Adaptec Shared/System:/usr/bin:/cygdrive/c/Program Files/SSH Communications Security/SSH Secure Shell:/bin
X-Cron-Env: PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
X-Cron-Env: PROCESSOR_ARCHITECTURE=x86
X-Cron-Env: PROCESSOR_IDENTIFIER=x86 Family 15 Model 4 Stepping 3, GenuineIntel
X-Cron-Env: PROCESSOR_LEVEL=15X-Cron-Env: PROCESSOR_REVISION=0403
X-Cron-Env: PROGRAMFILES=C:\Program FilesX-Cron-Env: SYSTEMDRIVE=C:
X-Cron-Env: SYSTEMROOT=C:\WINDOWS
X-Cron-Env: TMP=/cygdrive/c/DOCUME~1/SODO/LOCALS~1/Temp
X-Cron-Env: TEMP=/cygdrive/c/DOCUME~1/SODO/LOCALS~1/Temp
X-Cron-Env: WINDIR=C:\WINDOWSX-Cron-Env: SHELL=/bin/sh
X-Cron-Env: HOME=//SAN/Users$/SODO
X-Cron-Env: LOGNAME=SODO

4) My scripts do such things as SSH into other boxes and grab HTTP connection counts. The scripts only ran using the CYGWIN environment variable set to smbntsec.


5) the HOME environment variable must be set properly: http://blog.spikesource.com/crontab.htm suggests running "env" in your cron out to a file to find differences between your user environment and the cron environment. Good idea!

6) don't forget your scripting basics:
/2007/07/why-doesnt-my-shell-script-run-under.html

7) documentation can help:
C:\cygwin\usr\share\doc\Cygwin\cron-4.1-6.README


Or whatever the latest version happens to be..

Mail That Cron Sends

Change the email that cron sends error messages to:
http://www.cyberciti.biz/faq/linux-unix-crontab-change-mailto-settings/
or
run cron-config
or
Add/edit the "From:" address in /etc/ssmtp.conf

Hope these tips help!
sodo

No comments:

Feel free to drop me a line or ask me a question.