Wednesday, January 4, 2012

Date command in Linux

Man page of date will give you more info than anything else, it is a very descriptive one.
I wanted to hightlight few of the options used and thier alternatives, mainly the option "-d". Why because it looks like solaris version of date does not have "-d" option.

The man page says

       -d, --date=STRING
              display time described by STRING, not `now'

Lets take few examples

Firing the date command would give you the date

Code:
root@bt > date
Wed Jan  4 07:52:17 IST 2012

Do you want to customize this? No problem. Use the format control. There are like more than 20 format control options.

Say, you want the date in DD/MM/YYYY format

Code:
root@bt > date '+%d/%m/%Y'
04/01/2012

       %d     day of month (e.g, 01)
       %m     month (01..12)
       %Y     year

Want the current date in seconds since the epoch? Use "+%s" option

Code:
root@bt > date '+%s'
1325644010

       %s     seconds since 1970-01-01 00:00:00 UTC

As you can see, "+" is mandatory which is followed by the format specifier.

To set/change the system date, use the "-s" option.

       -s, --set=STRING
              set time described by STRING

Code:
root@bt > date
Wed Jan  4 08:21:47 IST 2012

root@bt > date -s "Mon Dec 31 00:00:00 IST 1990"
Mon Dec 31 00:00:00 IST 1990

root@bt > date
Mon Dec 31 00:00:01 IST 1990

Now, what does "-d" option do? Hmmm, if you see we were dealing with current system date till now. What if you want to do the same with some other date? Well, that is where "-d" option comes to the rescue!

Say, you want to find the seconds since epoch till December 31 1990

Code:
root@bt > date -d "Dec 31 1990" '+%s'
662581800

You want to format a date given to you in "31 Dec 1990" to MM-DD-YY

Code:
root@bt > date -d "31 Dec 1990" '+%m-%d-%y'
12-31-90

Cool right? Now, the "-d" option is not available in Solaris (not sure about 10 though).
Here is an alternative in awk for achieving the above

To get the time in seconds

Code:
root@bt > echo "Dec 31 1990" | nawk 'BEGIN{month="JanFebMarAprMayJunJulAugSepOctNovDec"}
{ print mktime($3" "int((index(month,$1)/3))+1" "$2" 00 00 00") }'
662581800

Code:
root@bt > echo "31 Dec 1990" | nawk 'BEGIN{month="JanFebMarAprMayJunJulAugSepOctNovDec"}
{ print int((index(month,$2)/3))+1"-"$1"-"substr($3,3) }'
12-31-90

We can practically do anything in awk! Check the right side link for AWK tutorial.

One more thing before we go, how do we convert the seconds to date?
Say, I have 662581800 (from our previous example), I want to convert it to actual date format

Code:
root@bt > date -d @662581800
Mon Dec 31 00:00:00 IST 1990

Note the "@" symbol before the seconds.

Also note that I have used nawk instead of awk, because in solaris the awk version is pretty old and it is kind of useless. Either use "nawk" or awk from this path "/usr/xpg4/bin/awk" in solaris.

Good Day!

Tuesday, January 3, 2012

Command Substitution in Linux

In Linux, we do a lot of onliners on the shell. Something like,

Code:
root@bt > date
Tue Jan  3 01:19:19 IST 2012

Now if we want to store this date into a variable, what do we do?
There are 2 ways in which we can achieve this i.e. command substitution

One way, using backticks i.e. `

Code:
root@bt > var=`date`
root@bt > echo $var
Tue Jan 3 01:20:47 IST 2012

Other way is using $(...)

Code:
root@bt > var=$(date)
root@bt > echo $var
Tue Jan 3 01:21:18 IST 2012

Command line or script, you can use it anywhere you want. I prefer the second way!

Note, there is no space between var = and the command. Why so? Because that is how it should be.
That is the syntax. If you have a space in between you will see strange errors.
Let us try it once with a space inbetween,

Code:
root@bt > var =$(date)
No command 'var' found, did you mean:
 Command 'jar' from package 'openjdk-6-jdk' (main)
 ...
 Command 'par' from package 'par' (universe)
var: command not found

Oops, we don't want that now, do we?

Good Day!

Sunday, January 1, 2012

File Creation Time in Linux

Actually, the creation time of any inode is(was) not stored anywhere. I wonder why they did that. Normally we get to see only the following :

ctime - change time
mtime - modification time
atime - access time

What about crtime - creation time?

But things have changed now. We can get the file creation time if your filesystem type is ext4.

First lets see how we can get the details of a file. There is a command called "stat" - display file or filesystem status.

Code:
root@bt > stat somefile
File: `somefile'
Size: 149 Blocks: 8 IO Block: 4096 regular file
Device: 804h/2052d Inode: 211582 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2012-01-01 20:21:15.276575811 +0530
Modify: 2012-01-01 20:21:14.256570755 +0530
Change: 2012-01-01 20:21:14.256570755 +0530

"somefile" is a normal ascii file. A "stat" on the file will give you all these details. You can also customize the output. Let us say you just want the size of the file.

Code:
root@bt > ls -lrt somefile
-rw-r--r-- 1 root root 149 2012-01-01 20:21 somefile
root@bt > stat -c %s somefile
149

-f will give you information about the file system.

Code:
root@bt > stat -f /dev/sda4
File: "/dev/sda4"
ID: 0 Namelen: 255 Type: tmpfs
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 255610 Free: 255524 Available: 255524
Inodes: Total: 214563 Free: 213660

Now, the -t option is interesting. If you want to get all this info in one line, use this option. This will be very helpful when it comes to scripts where we use stat to get various information into a variable and do some calculation etc.

Code:
root@bt > stat -t -f /dev/sda4
/dev/sda4 0 255 1021994 4096 4096 255610 255524 255524 214563 213660

So, we didn't get the file creation time yet! What do we do for that?
Ok, here it is
1. You will need a ext4 filesystem.
2. You will also need the debugfs -ext2/ext3/ext4 file system debugger utility which is normally available with any distros. If you don't have it, then simply install it.

Check List
Lets get some info on / and /dev/sda4.

Code:
root@bt > df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda4 14G 10G 2.6G 80% /
none 999M 344K 999M 1% /dev

Code:
root@bt > mount | grep sda4
/dev/sda4 on / type ext4 (rw,errors=remount-ro)

Cool! It is on ext4.

Once you have all that, then all you have to do is run the following command

Code:
root@bt >  debugfs -R 'stat /root/Desktop/somefile' /dev/sda4
debugfs 1.41.11 (14-Mar-2010)
Inode: 211582 Type: regular Mode: 0644 Flags: 0x80000
Generation: 1690641204 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 149
File ACL: 0 Directory ACL: 0
Links: 1 Blockcount: 8
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x4f0072e2:3d2bd60c -- Sun Jan 1 20:21:14 2012
atime: 0x4f0072e3:41f0d90c -- Sun Jan 1 20:21:15 2012
mtime: 0x4f0072e2:3d2bd60c -- Sun Jan 1 20:21:14 2012
crtime: 0x4f0072e2:3d2bd60c -- Sun Jan 1 20:21:14 2012
Size of extra inode fields: 28
EXTENTS:
(0): 772301
(END)

Do you see the crtime? Wow!


bc - a powerful calculator

"An arbitrary precision calculator language' - this is what the man page says. This is fairly a simple tool in term of usage.
For instance :- Just type in "bc" in your shell prompt and you have the tool running.

Code:
root@bt > bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.

22/7
3

See the "22/7", that is what I have typed in and there is the result. You can also use this like an one liner.

Code:
root@bt > echo " 22/7 " | bc
3

Hmmm I know, the decimals are missing right? No problem, we just need to tell the "bc" to print the decimals. Use "scale" for that purpose.

Code:
root@bt > echo " scale=5; 22/7 " | bc
3.14285


Wow! happy now? ;)

If you go thru the man page, you can see that whatever you do in C using the math lib, you can do it using "bc" as well. What got my attention is that, we can actually have our own functions written and call it.

Code:
root@bt > echo "define foo(a,b){ return a+b }; print foo(10,20)" | bc
30

Cool right? I mean look at the flexibility this small tool is providing you. Well, can't call this a small tool now, can we?
Just for information, I found another program "calc".

Code:
root@bt > calc
C-style arbitrary precision calculator (version 2.12.3.3)
Calc is open software. For license details type:  help copyright
[Type "exit" to exit, or "help" for help.]

; 22/7
~3.14285714285714285714
;

Check this out!

Code:
root@bt > bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.

scale=100
22/7
3.142857142857142857142857142857142857142857142857142857142857142857\
1428571428571428571428571428571428

I did try with a scale of 1000 and it worked!


Good Day!