Why are “executables” such as reboot, shutdown, and vgscan symlinks in the /sbin directory?

Background

If you’ve ever gone poking around in your Linux system’s /sbin directory the site of files like this might make you scratch your head.

1
2
3
4
5
6
7
8
lrwxrwxrwx  1 root root       3 Jun  7  2011 vgmerge -> lvm
lrwxrwxrwx  1 root root       3 Jun  7  2011 vgmknodes -> lvm
lrwxrwxrwx  1 root root       3 Jun  7  2011 vgreduce -> lvm
lrwxrwxrwx  1 root root       3 Jun  7  2011 vgremove -> lvm
lrwxrwxrwx  1 root root       3 Jun  7  2011 vgrename -> lvm
lrwxrwxrwx  1 root root       3 Jun  7  2011 vgs -> lvm
lrwxrwxrwx  1 root root       3 Jun  7  2011 vgscan -> lvm
lrwxrwxrwx  1 root root       3 Jun  7  2011 vgsplit -> lvm

We’ll read on and I’ll explain how all these seemingly regular tools are actually just one.

So What’s going on?

Many programs make use of this technique where there is a single executable that changes it’s behavior based on how it was executed.

There’s typically a structure inside the program called a case/switch statement that determines the name the executable was called with and then will call the appropriate functionality for that executable name. That name is usually the first argument the program receives. For example, in the C programming language when you write:

1
int main(char** argv, int argc)

argv[0] contains the name of the called executable. At least, this is the standard behavior for all shells, and all executables that use arguments should be aware of it.

Example in Perl

Here’s a contrived example I put together in Perl which shows the technique as well.

Here’s the actual script, call it mycmd.pl:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/perl
 
use feature ':5.10';
 
(my $arg = $0) =~ s#./##;
 
my $msg = "I was called as: ";
 
given ($arg) {
  $msg .= $arg  when 'ls';
  $msg .= $arg  when 'find';
  $msg .= $arg  when 'pwd';
  default { $msg = "Error: I don't know who I am 8-)"; }
}
 
say $msg;
exit 0;

Here’s the file system setup:

1
2
3
4
5
6
$ ls -l
total 4
lrwxrwxrwx 1 saml saml   8 May 24 20:49 find -> mycmd.pl
lrwxrwxrwx 1 saml saml   8 May 24 20:34 ls -> mycmd.pl
-rwxrwxr-x 1 saml saml 275 May 24 20:49 mycmd.pl
lrwxrwxrwx 1 saml saml   8 May 24 20:49 pwd -> mycmd.pl

Now when I run my commands:

1
2
3
4
5
6
7
8
9
10
11
$ ./find
I was called as: find
 
$ ./ls
I was called as: ls
 
$ ./pwd
I was called as: pwd
 
$ ./mycmd.pl
Error: I don't know who I am 😎

References

links
This entry was posted in linux, shell, Syndicated, sysadmin, tip, tutorials. Bookmark the permalink.

Comments are closed.