Friday May 08, 2009

Stopping find searching remote directories.

Grizzled UNIX users look away now.

The find command is a wonderful thing but there are some uses of it that seem to cause confusion enough that it seems worth documenting them for google. Today's is:

How can I stop find(1) searching remote file systems?

On reading the documentation the “-local” option should be just what you want and it is, but not on it's own. If you just do:

$ find . -local -print

It will indeed only report on files that are on local file systems below the current directory. However it will search the entire directory tree for those local files even if the directory tree is on NFS

To get find to stop searching when it finds a remote file system you need:

$ find . \\( ! -local -prune \\) -o -print


Friday Dec 12, 2008

Don't reboot to add swap on solaris.

Today I wish I had blogged this earlier after the second person who should have known better suggested that you need to reboot a system to increase the swap space when using ZFS for swap. The second one asserted it in such a way that the system I was using was rebooted!

Just like when we did not use zvols for swap you always had the option to have multiple swap devices that option is still there if you are using zvols. You can have multiple zvols just create them and add them to the vfstab so that when you do reboot you still have them. If however you don't like that you can always remove the existing swap device and add a new one of the new size.

Or if you really only want one swap volume and don't want to edit /etc/vfstab and like to live a little bit on the edge you can grow the swap device and then add the extra space as a new swap volume.

cjg@brompton:~$ swap -l
swapfile dev swaplo blocks free
/dev/zvol/dsk/rpool/swap 182,1 8 4126712 4111472
cjg@brompton:~$ pfexec zfs set volsize=4G rpool/swap
cjg@brompton:~$ pfexec zfs set reservation=4G rpool/swap
cjg@brompton:~$ pfexec env NOINUSE_CHECK=1 swap -a /dev/zvol/dsk/rpool/swap $((8+4126712))
cjg@brompton:~$ swap -l
swapfile dev swaplo blocks free
/dev/zvol/dsk/rpool/swap 182,1 8 4126712 4111472
/dev/zvol/dsk/rpool/swap 182,1 4126720 4261888 4261888

When the system is finally rebooted it will end up with just a single swap device again.

Obviously the correct answer is that the operating system should just “do the right thing” and to that end I have filed this RFE: 6783886The bug should turn up on in the next few days/hours.

Tuesday Mar 20, 2007

Don't IM.... talk!

I had to contact an engineer quite urgently today. First email, then IM, not logged in so I set a buddy pounce, then phone, got voice mail.

Finally got him.

Using good old talk(1)!

Welcome to UNIX.


Friday Jan 19, 2007

What timezone should a server run in?

Ever since the dawn of time (Thu Jan 01 00:00:00 GMT 1970) UNIX has been tracking time in GMT or possibly UTC for those with no sense of history. It is my contention, one that my server at home supports, that all servers should run with a default timezone of GMT. Yes it makes cron slightly more irritating than it could be for local users but unless all your users actually live in the same timezone how do you choose which one to use?

For any system that can be connected to globally you have to choose a timezone, why pick the one for the geographic location of the server when only a small fraction of the users will be in that location. No. Choose GMT, not GB, or GB-Eire but GMT with no springing forward or autuming back just plain simple GMT. Then run all your services in that timezone. If users want a different time zone they can set TZ for themselves.


Tuesday Oct 24, 2006

How to delete a lot of files from a directory.

If you have more than can be passed directly to a command.

v4u-3500f-gmp03 135 # rm test/test_dir/\*/\*                       
/usr/bin/ksh: /usr/bin/rm: arg list too long
v4u-3500f-gmp03 136 # echo test/test_dir/\*/\* | xargs rm
v4u-3500f-gmp03 137 # 

There are lots of other ways to skin this cat.


Thursday Mar 02, 2006

Logging commands in korn shell

Yet another blast from the past, but I was asked for this again today.

How can you log every command typed into a korn shell session? Here is the cheap and dirty but surprisingly useful way that logs them all into syslog.

Type this into your shell and you can capture the command, it's return code and the current working directory.

function dlog
        typeset -i stat=$?
        typeset x
        x=$(fc -ln -0)
        logger -p daemon.notice -t "ksh $LOGNAME $$" Status $stat PWD $PWD \\'${x#       }\\'
trap dlog DEBUG

(note that there is a tab after the # in “${x# }”)

You might want to use a different logging facility but that one gets it into /var/adm/messages:

Mar  2 14:44:15 estale ksh cg13442 497922: [ID 702911 daemon.notice] Status 0 PWD /home/cg13442 'ls'
Mar  2 14:44:18 estale ksh cg13442 497922: [ID 702911 daemon.notice] Status 1 PWD /home/cg13442 'false'
Mar  2 14:45:09 estale ksh cg13442 497922: [ID 702911 daemon.notice] Status 0 PWD /home/cg13442 'ls -la'

I had run ls, false and “ls -la” which is dutifully logged.


Thursday Sep 01, 2005

Sad shell programming problem

While I was away an email ended up in my mail box like this:

I have a question on scripting ...

I want a "timedwait" for a background process started from a shellscript, i.e. do something like:

while [ 1 ]; do
        start_bg_job &
        "timedwait $! 30" || kill -9 $?

i.e. wait for the background job termination - but no more than 30 secs, if it didn't finish then kill it hard.

There were a couple of replies but none of them were “pure” shell scripts but it was weeks ago so who cares. Well it nagged at me last night as I cycled home. There has to be away to do this from the korn shell, and as usual the answer came to me just outside Fairoaks Airport (that is the answer came to me as usual while cycling home rather than outside the Airport.. If all the answers came to me outside the Airport I would be there a lot).

The trick (hack may be more appropriate) is to use a co process and start both the command you wish to run and a sleep command in the background in a sub shell that is the co process. When each of the commands return you echo information as to what to do back to the parent process which reads from the co process and takes the appropriate action.

So I ended up with this shell function:

#!/bin/ksh -p

# run_n_wait “command” [timeout]
function run_n_wait
        typeset com command time pid arg


        ( ( ( $command ) > /dev/null 2>&1 & \\
                echo pid $! ; wait $! ;\\
                echo Done $? ) & \\
         (sleep $time ; echo kill ) & ) |&

         while read -p com arg
                case $com in
                kill)  if [[ "${pid}" != "" ]]
                                kill ${pid} > /dev/null 2>&1
                                wait ${pid}
                        return -1 ;;
                pid) pid=$arg ; arg="" ;;
                Done) return $arg ;;

run_n_wait "/bin/false" 3
echo Slept for $(($SECONDS - $x)) seconds ret $?
run_n_wait "sleep 5 " 
echo Slept for $(($SECONDS - $x)) seconds ret $?
run_n_wait "sleep 60" 3
echo Slept for $(($SECONDS - $x)) seconds ret $?

Yes there are lots of shells that could just do this out of the box but that was not the question. If you have a better way (korn shell, bourne shell only) let me know.


Thursday May 05, 2005

Base Conversion

Some one in a chat room asked about converting from hex to decimal. The usual answers came up, use mdb or adb or dtcalc oddly the vastly superior gnome-calculator did not get a mention. Anyway my solution was declared “cool” by one person so that is enough to get on the blog.

The solution is the korn shell. Converting from hex to decimal do this:

echo $(( 16#4000 ))

Will convert 4000 to decimal

Converting to hex is slightly harder:

typeset -i16 x
echo $x

Which cries out for a shell function:

function convert_base
        typeset -i${2:-16} x
        echo $x

Putting that in a file called convert_base in your FPATH thus allowing:

: FSS 12 $; convert_base 4000
: FSS 13 $; convert_base 4000 2
: FSS 14 $; convert_base 16#4000 2
: FSS 15 $; convert_base 16#4000 10
: FSS 16 $;

Well I like it.

Tag: , ksh


Friday Apr 01, 2005

grep piped into awk

This has been one of my bug bears for years and it comes up in email all the time. I blame it on the VAX I used years ago that was so slow that this really mattered at the time but now, mostly it is just because it is wrong. This is what a mean, grep piped into awk:

grep foo | awk '{ print $1 }'

Why? Because awk can do it all for you, saving a pipe and a for and exec:

nawk '/foo/ { print $1 }' 

is exactly the same, I use nawk as it is just better. It gets worse when I see:

grep foo | grep -v bar | awk '{ print $1 }'

which should be:

nawk '/foo/ && ! /bar/ { print $1 }'

Mostly these just come about when typed on the command line but when I see them in scripts it just caused me to roll my eyes. They lead me to come up with these short rules for pipes:

If your pipe line contains


grep and awk


grep and sed


awk and sed


awk sed and grep


Like the pirates code these are not so much rules as guide lines.


This is the old blog of Chris Gerhard. It has mostly moved to


« April 2014