Andrew Stribblehill: The story of ping(1)
How we laughed when we discovered that Linux s ping makes a reverse DNS lookup for every incoming ICMP echo reply! For added mirth and/or merriment, it also happens on flood-ping.
ls --color
is useful. It can show you which items in your directory listing are directories, symlinks, broken symlinks, device nodes, named pipes, whatever. I am glad that it exists.
However, let’s consider the basic action of ls. It is, of course, to display which files and directories exist in a directory. This is really quick and easy in Unix. Simply use the libc function opendir()
then just readdir()
till it returns NULL
and errno
is 0. In terms of syscalls, this is an open()
, one or two read()
s and a close()
.
When you turn on the color
option, every directory item incurs the weight of an extra stat()
call to see what it is.
Worse still, if it’s a symlink, ls
will obligingly bound across to the thing linked to, to check it exists. If this causes your automounter to wake up and mount something remote, that’s quite an overhead. If your mount hangs because the remote filesystem is unavailable, you can say goodbye to that process; it'll be stuck blocking on a syscall that will never return.
A partial solution
To fix the symlink problem, here’s what you do. ls
was written to avoid chasing symlinks if configured not to. Check your environment variables for the LS_COLORS variable with:
$ env grep ^LS_COLORS
If it exists, you have a config file for colour ls: you should edit /etc/DIR_COLORS*
or copy it to $HOME/.dircolors
and edit it there. Otherwise, type:
$ dircolors --print-database > $HOME/.dircolors
The edit you need to do is to remove or comment out the ORPHAN line from the file.
Unless you were able to edit the file in /etc
, you now need to make sure that this new $HOME/.dircolors
file is used. In your shell login script (.bash_login
for bash and .login
for (t)csh, put the line:
eval dircolors $HOME/.dircolors
(Note that these are backticks, not apostrophes.)
Next time you log in, you'll be able to use colourful ls without fear of a remote filesystem freezing your directory listings.
In conclusion
Use ls --color
when you need it, but as with all powerful tools, use it with care.
Corrections: James pointed out that to dump the default config it is –print-database not –print-directory.
time sudo perl -we '$disk="/dev/sda"; $n=1500; $blocks= blockdev --getsz $disk ; if (!$blocks) print "Enter capacity in manufacturer GB\n: "; $blocks=1953125*(
) ; use Time::HiRes "time"; open DISK, $disk; $start=time; for (0..$n) seek DISK, int(rand($blocks))*512, 0; sysread DISK, $x, 512 die; $now=time; $times[int(($now-$start)*1000)]++; $x=$now-$start; $s2+=$x**2; $s+=$x; $start=$now ; for (0..$#times) if ($t=$times[$_]) $tot+=$t; $median =$_ if $tot>=$n/2; printf "%3d %s\n", $_, "x" x ($t/2) . ($t%2?":":"") ; printf "\nTook %3.4gs for %d seeks of %s (%d GB)\n", $s, $n, $disk, $blocks/2097152; printf "Mean: %2.03gms; Median: %d-%dms; Std dev: %2.03gms\n", 1000*$s/$n, $median-1, $median, 1000*sqrt($s2/$n - ($s/$n)**2);’
It should be obvious that before you run this, you should check for yourself that it doesn’t do anything dangerous. Or at least check that $disk is set appropriately for your hardware and operating system. If you don’t have blockdev, estimate the number of 512-byte blocks and set $blocks to that value. (There are 1953125 blocks in a hard disk manufacturer’s "Gigabyte".)
The graph it produces prints an ‘x’ for two seeks of a given number of milliseconds and a trailing ‘:’ if there was one left over. For me, on my one year old Linux 2.6.18 workstation with a 160 "GB" Western Digital (WDC WD1600JS — quoted seek time 8.9 ms) the typical output is:
0 : 3 : 4 : 5 x: 6 xxxx: 7 xxxxxxx 8 xxxxxxxxxxx: 9 xxxxxxxxxxxxxxxxx 10 xxxxxxxxxxxxxxxxxxxxxxx 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxx: 12 xxxxxxxxxxxxxxxxxxxxxxxxx 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 23 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 24 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 25 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 26 xxxxxxxxxxxxxxxxxx 27 xxxxxxxxxxxxxxx 28 xxxxxx: 29 xxxxx: 30 xxxx 31 : 32 : 34 x 35 : 57 : Took 27.69s for 1500 seeks of /dev/sda (149 GB) Mean: 18.5ms; Median: 17-18ms; Std dev: 5.24ms real 0m27.859s user 0m0.116s sys 0m0.044sWhy might I care? 18 milliseconds is almost a lifetime compared with anything else a modern PC does. It’s slower than my monitors’ refresh period! I can read around 1 MB from disk, 10 MB over a GigE link or 20 MB from RAM in this time. I can ping from Ireland to England, crossing 40 routers there and back, in the time it takes for my disk head to seek. Every time you read something from a previously unread file, it costs on average EIGHTEEN MILLISECONDS even before it starts reading. That’s just 55 in a second. This has obvious implications for I/O program performance, i.e. that of most servers. If anyone has a concern about my method, I’d be interested to hear it. I’d also like to see the timings for different disks. Either post the whole histogram or just the stats, plus the make and model of the disk. On Linux you can get this from dmesg or hdparm -I device. Update: I’ve made the script more robust under non-existence of
blockdev
.
$ dpkg-repack <pkg>So, here’s a hacky and woefully incomplete replacement for dpkg-repack.
bash: dpkg-repack: command not found
#! /bin/sh set -euWorks For Me ™. Update: it was pointed out that wordpress had prettified the code, turning pairs of dashes into em-dashes and other atrocities. so I’ve uploaded the script: [fake-repack]
[ 0 != $(id -u) ] && echo “Must be run as (fake)root” 1>&2; exit 1; pkg=$1; pkgdir=$(mktemp -d “$pkg.XXXXXX”)
mkdir “$pkgdir” dpkg -L $pkg tar cf - –no-recursion –files-from - (cd “$pkgdir” && tar xvf -) install -d -m 755 “$pkgdir/DEBIAN”
dpkg -s “$pkg” sed ‘/^Status: /d’ > “$pkgdir/DEBIAN/control” dpkg-deb -b “$pkgdir” .
rm -rf “$pkgdir”