Monday, September 29, 2008

Unix soft link and hard link

To simply put it, a Unix link is a convenient way to access data of a file. It is similar to shortcuts in windows. But in UNIX there are two types of links, soft link and hard link. To understand the difference between these two, we should first know some basics of Unix file structure.

In UNIX file system, a file contains two parts, data part and filename part. Filename part contains the file name and indoe. Data part contains the actual data stored in the file. Inode is a data structure that contains the information about the file like permissions, group, owner, pointer to the data part etc….Each inode (and hence the data it points to) is identified by an inode number. Data part contains the actual data stored in the file. A user accesses a file using its name while the underlying file system access it with its inode number.

Different files can point to the same inode number. These files are called hard links. They will have different names and may be located in different paths, but under the same file system. Hard links can’t be created across different file systems, this is because the inode number is specific to a file system not the OS as a whole. Each file system maintains a table of inodes within that file system.

A soft link is a special file that contains the file system path to another file as its data. But as soft link (symlink) is a special file, any read/write/modify operation on this file will be redirected to the target file. Since symlinks refer to their target using absolute path and file name, it can cross file system boundaries and can be located anywhere. Soft links can point to both files and directories.

Difference b/w soft and hard links


Soft link

Hard Link

Points to file name of original file

Points to inode of original file

Can link between file systems

Can link only within same file system

Both for file & directory

Only for files

Default permission 777

Default permission 644

Can’t access data after original file is deleted

Can access data even after original file is deleted

Can’t change owner/group/permission

Can change owner/group/permission

Inode number not same as original file

Inode number same as original file


Now create a text file

[root@penguin007 links]# touch link-test.orig
[root@penguin007 links]# echo “Original file created” > link-test.orig
[root@penguin007 links]# cat link-test.orig
Original file created

The command to create link is "ln". Let us create a hard link to the file link-test.orig.

[root@penguin007 links]# ln link-test.orig link-test.hard

Now let us create a soft link to the file link-test.orig.
[root@penguin007 links]# ln -s link-test.orig link-test.soft
[root@penguin007 links]# ls -li
total 8
163774475 -rw-r–r– 2 root root 22 Jul 19 13:38 link-test.hard
163774475 -rw-r–r– 2 root root 22 Jul 19 13:38 link-test.orig
163774476 lrwxrwxrwx 1 root root 14 Jul 19 13:47 link-test.soft -> link-test.orig

Now you can make changes to the original file/soft link/hardlink and the change will be reflected on all others. This is because all of these are pointing to the same data location

Edit from soft link

[root@penguin007 links]# echo “Change from soft link” > link-test.soft
[root@penguin007 links]# cat link-test.orig
Change from soft link
[root@penguin007 links]# cat link-test.hard

Change from soft link

Edit from hard link

[root@penguin007 links]# echo “Change from hard link” > link-test.hard
[root@penguin007 links]# cat link-test.orig
Change from hard link
[root@penguin007 links]# cat link-test.soft

Change from hard link

Edit from original file

[root@penguin007 links]# echo “Change from original” > link-test.orig
[root@penguin007 links]# cat link-test.soft
Change from original
[root@penguin007 links]# cat link-test.hard

Change from original

From the output of "ls -li" you can observe following points.

Both the original file and hard link are having same inode (163774475 - column 1 ). In fact both these files are referred to as hard links and you can't distinguish which file is original and which one is link - there is no need to do that either.

Note the permission on the files, hard links are having standard 644 permissions while soft link has 777 permission. Hard links are treated as regular files but soft links are treated as links- note the first character in the 2nd column of "ls" output above ("-" for regular file/hard link and "l" for soft link)

When you change permission/ownership of a hard link the change is reflected on all hard links. But when you change permission/ownership of a softlink the change is applied to the original file (and its hard links if any) while soft link retains the permission and ownership.

[root@penguin007 links]# chmod 755 link-test.hard

[root@penguin007 links]# ls -li
total 8
163774475 -rwxr-xr-x 2 root root 22 Jul 19 13:38 link-test.hard
163774475 -rwxr-xr-x 2 root root 22 Jul 19 13:38 link-test.orig
163774476 lrwxrwxrwx 1 root root 14 Jul 19 13:47 link-test.soft -> link-test.orig
[root@penguin007 links]# chmod 644 link-test.soft
[root@penguin007 links]# ls -li
total 8
163774475 -rw-r–r– 2 root root 22 Jul 19 13:38 link-test.hard
163774475 -rw-r–r– 2 root root 22 Jul 19 13:38 link-test.orig
163774476 lrwxrwxrwx 1 root root 14 Jul 19 13:47 link-test.soft -> link-test.orig
[root@penguin007 links]# chown safeer link-test.orig
[root@penguin007 links]# ls -li
total 8
163774475 -rw-r–r– 2 safeer root 22 Jul 19 13:38 link-test.hard
163774475 -rw-r–r– 2 safeer root 22 Jul 19 13:38 link-test.orig
163774476 lrwxrwxrwx 1 root root 14 Jul 19 13:47 link-test.soft -> link-test.orig
[root@penguin007 links]# chown root link-test.soft
[root@penguin007 links]# ls -li
total 8
163774475 -rw-r–r– 2 root root 22 Jul 19 13:38 link-test.hard
163774475 -rw-r–r– 2 root root 22 Jul 19 13:38 link-test.orig
163774476 lrwxrwxrwx 1 root root 14 Jul 19 13:47 link-test.soft -> link-test.orig

The third column in the output shows the hard links count, ie; how many hard links point to that file (2 in our case).

Links do not cause any additional hard disk usage. We can check it now:

[root@penguin007 links]# du -hs ./*
4.0K ./link-test.hard

0 ./link-test.soft

You may note that only one file (that comes alphabetically first) of the hard links is displayed in disk usage result (this happens if both hard links are in the same directory)

Now let us delete the original file.
[root@penguin007 links]# rm -rf link-test.orig
[root@penguin007 links]# cat link-test.hard
Change from hard link
[root@penguin007 links]# cat link-test.soft

cat: link-test.soft: No such file or directory

As you can see, soft link will not work if the original file is deleted, because it points to the name of the original file. But hard links are pointing directly to the inode, so it can continue accessing the data. When a file has multiple hard links, the data part of the file will not be deleted until all the hard links to the file are deleted. The count of hard links is stored in the inode which will be decremented every time a hard link to that data is deleted.

VNC Desktop in Linux

#su - safeer
[safeer@xmsv03 ~]$ mkdir .vnc
[safeer@xmsv03 ~]$ vi .vnc/xstartup
----------------------
#!/bin/sh

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &

unset SESSION_MANAGER
exec /etc/X11/xinit/xinitrc
------------------------------------------------
[safeer@xmsv03 ~]$chmod a+x .vnc/xstartup
[safeer@xmsv03 ~]$vncpasswd
Password:
Verify:

[safeer@xmsv03 ~]$vncserver -extension XFIXES

New 'xmsv03:2 (safeer)' desktop is xmsv03:2

Starting applications specified in /home/safeer/.vnc/xstartup
Log file is /home/safeer/.vnc/xmsv03:2.log

Note that vncserver for safeer is started at display 2 (xmsv03:2) which will by default listen on port 5902 of remote machine
Now access remote linux desktop via VNC viewer

This will prompt for the password you set using vncpasswd command

To stop the server, use command

[safeer@xmsv03 ~]$ vncserver -kill :2

Setting up your first SVN Repository



This article is based on windows platform, but you can use the same commands on linux also. The only difference will be in the choice of text editor for modifying configuration files- which will be VIM for linux. In windows before setting up an svn repository for your project, make sure that all the svn binaries are available in the system path. For details on installation and configuration of Subversion server, see the related articles in this website.

Find out the SVN root for the projects, let us say C:\svnroot\
Now we can create a test project under svn root.
C:\Temp>svnadmin create C:\svnroot\samplepro
Now setup authentication for this project
Open C:\svnroot\samplepro\conf\svnserve.conf in notepad
Under the section marked [general] find the commented lines:
#anon-access = read
#auth-access = write

This allows anonymous users read access and authenticated users write access to the project source code. This is not desirable in a corporate environment -unless you are working on a project under GPL. So let us deny anonymous users any kind of access while allowing write access to authenticated users.
anon-access = none
auth-access = write

Uncomment the line
#password-db = passwd
This will tell svnserver that the password database to be used is named passwd and is in the same directory as that of svnserve.conf.
* It is a good idea to keep a common password database for all project that has to be accessed by the same users.

Uncomment the line
#realm = My First Repository

Edit the realm name to describe your Project, say

realm = Web Projects
* If you are planning to use the same user database for multiple projects, They all should have the same Realm. This will let the clients use the same cached passwords for all repositories with this realm name.

Now add users to the user database
Open C:\svnroot\samplepro\conf\passwd

Under the [users] section, delete the commented username password pairs
# harry = harryssecret
# sally = sallyssecret

then add your own usernames

safeer = af12@#dr$
murali = oh8$%q23

Now try accessing the repository via svn command line client.

winws07.safeer.in is the host name of this machine

C:\Temp>svn co –username=safeer svn://winws07.safeer.in/samplepro
Authentication realm: <svn://winws07.safeer.in:3690>> Web Projects
Username: safeer
Password for ’safeer’: ******
Checked out revision 0.

Now you can use Any GUI svn clients either as stand alone or as part of your IDE to access this repository.

If you want a stand alone client for windows, go for Tortoise SVN at http://tortoisesvn.tigris.org/
If you are using eclipse, you can get the sub ecliepse pluggin for SVN. This varies with your IDE. Even if your IDE doesn’t support SVN, you can use custom scripts to do the job, depending upon the OS platform you use.

Tuesday, September 23, 2008

Output buffering in PHP

I was cleaning up the code of a small php application that I wrote long time back. The application was working fine on an old hosting account where it was sitting untouched for almost two years. I was running this application on my local LAMPP installation when I encountered this error:

"Warning: Cannot modify header information - headers already sent by (output started at /opt/lampp/htdocs/sec-app/index.php:35) in /opt/lampp/htdocs/sec-app/index.php on line 86"

Now I was a bit surprised (I don't have much experience in PHP) since this was running fine in that old server and both this and my lampp instance were in PHP5/Apache 2. After searching for sometime I found out that this was due to multiple calls to the php header() function even after the script started outputting html. The remedy was to enable PHP output buffering which I did in the php.ini file. Before going into the configuration, something about output buffering:

Normally, session, cookie or HTTP header data in a PHP script must be sent before any output is generated by the script. If this is not possible in your application, you can enable what PHP calls output buffering, with the output_buffering variable. With output buffering on, PHP stores the output of your script in a special memory buffer and sends it only when explicitly told to do so. This allows you to send special HTTP headers and cookie data even in the middle or at the end of your script;but thsi can have an adverse effect in performance.


output_buffering = Off

You can also pass the output_buffering variable a number indicating the size of the buffer, like:

output_buffering = 1024

I set the value in my php.in as:

output_buffering =4096

That is the default value advised in php.ini. If you want to set this on your production server, you should think about the performance issues. If you don't have access to php.ini on your web server, you can set the same in your .htaccess file as

php_flag output_buffering on

OR

php_value output_buffering 4096

You can add the same setting under a "Directory" directive in apache's httpd.conf file. If even this is not possible or you are not sure about the environment were the script will run, you can enable output buffering in your script itself. Immediately after your php tag opens add the line ob_start(); and immediately before the closing php tag add ob_end_flush(); - or you can enclose the code that causes the error alone within this function duo.

A complete reference of the php.ini variables can be found at: http://www.php.net/manual/en/ini.php

Monday, September 15, 2008

Running a linux command in absolute silence

Just wanted to get the exit status of a command while all its output was to be suppressed. Redirecting both stdout and stderr of a command to a file is achieved by "command &>file". To suppress both the outputs, we just need to send them to /dev/null. My real problem was to create a list of DNS resolvable hostnames from a list of hosts. The "host" command's exit status is used to check whether the host is resolvable and build the host list.

for host in `cat all-hosts `;do host -t A $host &>/dev/null && echo $host >> real-hosts;done