Wednesday, November 28, 2012

Setting crontab with Environment variables

Though I can boast of working on Ubuntu for past 1 year, but I am not quite handy in Linux/Unix. Very small tasks create different problems to me. Yesterday I was assigned to configure a crontab expression and test one application. But I was not able to define this crontab expression due to my negligence about CRONTAB_ENV.
I think lots of people, like me, face this issue while running crontab. So let's understand crontab environment. Let’s understand the intricacies of crontab.

Crontab
Crontab is a shell script to enable scheduling. We use crontab to configure the execution of any application periodically without any human intervention.
Each user has their own crontab, and commands in any given crontab will be executed as the user who owns the crontab.

Different options for Crontab
crontab -e Edit your crontab file, or create one if it doesn’t already exist.
crontab -l Display your crontab file.
crontab -r Remove your crontab file.
crontab -v Display the last time you edited your crontab file. (This option is only available on a few systems.)

Understanding and Setting crontab environment
Blank lines and leading spaces and tabs are ignored. Lines whose first non-space character is a pound-sign (#) are comments, and are ignored. Note that comments are not allowed on the same line as cron commands, since they will be taken to be part of the command. Similarly, comments are not allowed on the same line as environment variable settings.

An active line in a crontab will be either an environment setting or a cron command. An environment setting is of the form,
                 name = value
where the spaces around the equal-sign (=) are optional, and any subsequent non-leading spaces in value will be part of the value assigned to name. The value string may be placed in quotes (single or double, but matching) to preserve leading or trailing blanks. Several environment variables are set up automatically by the cron daemon.

SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd line of the crontab’s owner. HOME and SHELL may be overridden by settings in the crontab; LOGNAME may not. In addition to LOGNAME, HOME, and SHELL, cron will look at MAILTO if it has any reason to send mail as a result of running commands in "this" crontab. If MAILTO is defined (and non-empty), mail is sent to the user so named. If MAILTO is defined but empty (MAILTO=""), no mail will be                sent. Otherwise mail is sent to the owner of the crontab.

The MLS_LEVEL environment variable provides support for multiple per- job SELinux security contexts in the same crontab.

Few environment variable can be defined in the cronfile. By default cron jobs do not consider USER defined variables, but you can explicitly tell it to use user defined variables.

0 5 * * * . $HOME/.profile; /path/to/command/to/run

Cron expression and fields


Field          Allowed Values
-----          --------------
Minute         0-59
Hour           0-23
Day of Month   1-31
Month          1-12, jan, feb, mar, apr, may, jun, jul, aug, sep, oct, 
               nov, dec
Day of Week    0-7, sun, mon, tue, wed, thu, fri, sat (0 and 7 are "sun")

So expression mentioned above says run the /path/to/command/to/run script at 5AM everyday.

Cron Security
Though each user has it's cron file, but few cron expression are accessible to different users. cron.deny and cron.allow files contain the user allowed to run an expression.

I will rest my case of cron expression now. I will update this if I get some more information about cron.

Monday, November 26, 2012

Compilation Error: Byte Operations b = b + 1

Yet we have worked so much in Java, but still we are not aware all intricacies of the languages. Even after knowing so much it seems comes up with something new to astonish me. It is like a disillusion charm, which keeps me under the covers.

Here we are talking about byte operations.

Create a class and type the following lines in a method.

byte b = 0;
b++;
b = b + 1;

Now you will realize eclipse shows a compile time error, but why it is not a consistent behavior between line 2 and line 3.

But we must understand the difference between these 2 operations.
Though in theory b++, b+1 are same statement, but for compiler those are not same statement. 

In case of b++, compiler knows the value of b and internally it is adding 1, whereas b + 1 is operation between a byte and an integer. Though 1 is constant, but compiler understands it as integer.

So we can make some change in code and it should work.

byte b = 0;
b++;
b = b + (byte) 1;

Still it is a compile time error. Now what? I have converted 1 to byte and I am adding 2 bytes, now what is the problem.

So the problem is compiler. For these operations(+ , -, *) it uses 4 bytes atleast, i.e. minimal results of these operations is int.

So b + (byte) 1; still results in integer, which must be type-casted to byte. So following code will work perfectly fine.

byte b = 0;
b++;
b = (byte) (b + 1);

If you finalize the byte variable, then it is possible to add two bytes without typecasting.

final byte b = 117;
final byte c = 10;
byte d = b + c;

In this case b, and c are constants and they values will not change after this operations. So compiler know that d = 127 which is maximum allowable byte. So it works without causing any issue.


final byte b = 118;
final byte c = 10;
byte d = b + c;

But at this time compilation fails as 128 is an integer not a byte, so compiler needs explicit downcast.


final byte b = 117;
final byte c = 10;
byte d =(byte)( b + c);

Byte operations and questions are tricky so keep such things in mind before answering them in interviews. I could not find the reference, but will post that reference soon.