AnalogClock






Showing posts with label osx. Show all posts
Showing posts with label osx. Show all posts

Friday, August 1, 2008

Automate ssh-agent loading and sharing across logins

When the keychain package is not available on a platform I usually use a simple script in my .profile or .bash_profile or .bashrc that loads or reuses an existing ssh-agent.  This allows me to load an ssh key once and use it in any terminal without any additional effort. Like so:

# ssh-agent sharing
if [ -e ~/.ssh-agent ]; then
. ~/.ssh-agent
else
eval $(ssh-agent|tee ~/.ssh-agent)
fi

I tried sprucing it up for Terminal on my iPhone because it starts 4 simultaneous terminals at the same time. My first attempt was a dismal failure. I misguidedly added the following above the previous script:

# ssh-agent sharing - failed multiple concurrent launch attempt
if { ps awx |grep ssh-agent ; } then
if [ -e ~/.ssh-agent ]; then
. ~/.ssh-agent
else
killall ssh-agent
rm ~/.ssh-agent
fi
fi

I ended up finding a relatively simple file locking script:

function my_lockfile ()
{
TEMPFILE="$1.$$"
LOCKFILE="$1.lock"
{ echo $$ > $TEMPFILE ; } &> /dev/null || {
echo "You don't have permission to access `dirname $TEMPFILE`"
return 1
}
ln $TEMPFILE $LOCKFILE >& /dev/null && {
rm -f $TEMPFILE
return 0
}
kill -0 `cat $LOCKFILE` >& /dev/null && {
rm -f $TEMPFILE
return 1
}
echo "Removing stale lock file"
rm -f $LOCKFILE
ln $TEMPFILE $LOCKFILE >& /dev/null && {
rm -f $TEMPFILE
return 0
}
rm -f $TEMPFILE
return 1
}

Which makes it relatively easy to rewrite the script like so:

until my_lockfile ~/.sshagent; do
sleep 1
done

if [ -z "$SSH_AGENT_PID" ]; then
if [ -e ~/.ssh-agent ]; then
. ~/.ssh-agent >& /dev/null
else
eval $(ssh-agent|tee ~/.ssh-agent) >& /dev/null
fi
fi

if ! ps -p "$SSH_AGENT_PID" >& /dev/null; then
eval $(ssh-agent|tee ~/.ssh-agent) >& /dev/null
fi

rm -f ~/.ssh-agent.lock

The import part is the loop at the beginning of the script and the rm at the end.
I could add in a timeout but the lockfile script is pretty good at cleaning up unused lock files. Worst case scenario you can Ctrl-C to break out of the startup script.
If you need help with the basics of using ssh keys and the ssh-agent follow this link:
Automate a Remote Login Using SSH - Webmonkey
Blogged with the Flock Browser

Saturday, May 17, 2008

Automounting Kubuntu NFS Shares in OS X Leopard

I discovered this feature in OS X Leopard by accident. I thought I was sshed into my Kubuntu home server. I was having some problems with my NFS sharing setup across my MacBook Pro and Kubuntu boxes. I resolved the problem very easily by editing the nfs defaults file and making sure stats and idmap2 were enabled.

I was still having problems with a Seagate external USB drive. I had previously dealt with the problem of the drive going to sleep forever by using sdparm to change the sleep timeout to a day and had a cron script tap the drive twice a day. But the drive had been getting noticibly louder from constantly spinning. A little research turned up an elegant fix using udev to set the drive can be restarted /sys filesystem attribute to true on creating the device node for the drive.

Here's the trick for reference:


$ cat /etc/udev/rules.d/local.rules
# Seagate FreeAgent allow_restart fix (i/o errors)
SUBSYSTEMS=="scsi",DRIVERS=="sd",ATTRS{vendor}=="Seagate*", ATTRS{model}=="FreeAgent*",RUN+="/bin/sh -c 'echo 1 > /sys/class/scsi_disk/%k/allow_restart'"


Now back to problem of the drive not mounting on boot. I decided to install the autofsd and automount tools. So that whether or not the drive showed up at at a different SCSI device address it would mount at the same place. I also wanted any access to the Seagate external drive to kick off a mount if the Seagate external USB wasn't already mounted and for the filesystem to be umounted when idle.

Using automount/autofs would kill two problems I was having. The first problem was that the drive wasn't unmounting before it went to sleep. Leaving the filesystem locked and mounted to the ghost device. The second problem was that I couldn't count on the drive being at the same device name. I'm using the drive as the location of my MythTV recording directory and for my shared network file storage.

Enabled auto.misc in /etc/auto.master and added these lines to /etc/auto.misc:


mythtv -fstype=reiserfs :LABEL=500gusb
ubuntu -fstype=iso9660,loop,ro :/mythtv/downloads/ubuntu-8.04-desktop-i386.iso


I tried to get them to mount off the root filesystem but that is apparently a no no for automounting. At least it didn't work for me. A little filesystem linking covered that up. Notice the fine LABEL= device syntax. :) I added the Ubuntu ISO automounting and sharing so my other Kubuntu boxes could upgrade using the CD over NFS. I left the autofs loop in there since it is pretty light weight. It only mounts the image on access and unmounts it while idle. It inspired me to fiddle with the /etc/auto.master on all the Kubuntu boxes and enable auto.net. Allowing me to access the shared automounted filesystems with a simple reference to /net/<hostname>/<sharename>.

The /etc/exports (I decided to export each automount individually because NFS complained in the logs about exporting /misc even though it worked with the crossmount option.):


/misc/mythtv *.local(rw,async,nohide,no_root_squash,no_subtree_check,insecure)
/misc/ubuntu *.local(rw,async,nohide,no_root_squash,no_subtree_check,insecure)



Which brings me back to my original point of accidentily finding that Mac OS X Leopard is using the proper auto.net script and that it is enabled by default. Meaning ls /net/<hostname>/<sharename> automounts NFS shares - no configuration needed. Allowing me to get rid of my netinfo custom automounts located under /mounts in the local netinfo directory. I then turned my /mythtv directory into a link using sudo -s and then ln -s /net/<hostname>/misc/mythtv /mythtv (I don't give my everyday account blanket sudo permissions ergo sudo -s first in order to execute a command without explicit sudo rights being granted).

One final note. Don't let the Finder make your links for you. The aliases Finder creates are not soft links and are invisible to the POSIX subsystem and even some Cocoa apps. Found that out the hard way. Even scared me for a bit after all that fine setup work. Nearly wiped the smug look off my face.

Sunday, March 9, 2008

sudoers on Mac OS X

In my last post I refer to a lot of commands that require superuser privileges without prefacing them with sudo. That is how I type the commands in.

So how do I do it? I don't login as a user with administrator privileges and I don't use su. I have a separate account with administrator privileges that I don't login to that I use as an unprivileged user in the username and password prompt to perform activities that require superuser privileges.

I used to su to the account with administrative privileges to run sudo commands. Until I educated myself a little bit by "man sudoers".

You should always use visudo to edit the /etc/sudoers file it checks the syntax of the file before committing your changes. Saving you from yourself by preventing you from thinking you have correctly made changes to the /etc/sudoers file when all you have done is locked out all your accounts with administrative privileges from performing any administrative tasks. visudo will notify you of an error and give you a chance to fix the problem or abandon your changes when you exit your editor before it commits your changes. If you decide to fix the problem visudo will relaunch your editor with the changes you made intact. It is up to you to decide whether to try repeatedly to get your syntax right or abandon your changes. I locked myself out of sudo on my Mac years ago by directly updating /etc/sudoers. I think I recovered from it by rebooting or fixing file permissions. Save yourself some time by always use visudo.

There are a couple of command line options to sudo that are very su like but stick to sudo's use your own password metaphor.

The "-s" command line option launches the user's own shell with superuser privileges. There are many options you can set that control what and whether any environment variables are carried over from the user's environment. The environment can also be cleared of certain environment variables and the forced setting of environment variables can be specified. In order to use the "-s" command line option to sudo you have to add the user's shell command to the list of executable programs. Which will usually be /bin/bash.

The "-i" command line option launches the root user's login environment. You can use an option to sudo to switch to a different user. You have to add the root user's shell to the allowed executable programs with the full path, /bin/sh.

By using either of these command line options to sudo you avoid having to repeatedly type sudo before every command. I also avoid having to add my everyday user to the administration group by adding just the commands I need for one liner's like port gem while still having a backdoor to any command through the shell command. There are a couple of installation programs that refuse to work with my setup. But they are easily fixed by logging in to my administration account to install them. The need to do that has become less over time.

Friday, March 7, 2008

Rails Requires RubyGems >= 0.9.4 Error on Mac OS X

Updated 2008-10-08:
Please note that I forgot to mention in this post the fact that Ruby on Rails is installed by default with OS X Leopard. This blog is most helpful to those who had previously installed rails using MacPorts and now want to move to the Apple supported version that comes with OS X Leopard.

I was following along with the Apple Developer Connection article that shows how to update and use the version of Ruby on Rails that comes with Mac OS X Leopard. I followed through the article without a hitch. Successfully creating the Events Rails Site and viewing it at localhost:3000. The only change I made outside of the article's instructions was to add the script/generate and script/console commands to the same place as the article recommends the script/server. I figured keeping the original data model definition commands with the rails project would help if I wanted to make any changes to the data model later. I moved the data model definition commands to a shell script located in the top directory of the project. Which will make a nice portable design convention. I have seen that method mentioned in a blog post before.

While I was browsing around the running instance of the Events rails site I decided to do a full update of all the gem packages on my system by way of "gem update" without the "--system". Big mistake or so I thought when I tried to start my own rails project a day later. I couldn't even get the generate commands to run. The response from every script/ command was the same "Rails requires RubyGems >= 0.9.4. I googled around for the solution which always seemed to say remove the Leopard version and install the MacPorts version. Which I didn't want to do since I was trying to get rid of the duplicate MacPorts packages in the first place. In fact I had thought I had removed all the ruby packages from MacPorts. But on reinspection I found 4 versions of Ruby installed and one active a la "port search ruby and installed". First I did a "port uninstall ruby and inactive" to get rid of the old versions. Then I found a ruby gem I had somehow missed when I had done a "port uninstall rb-* and installed". After removing the lone gem I got rid of the installed and active version of Ruby via "port uninstall ruby". A quick verification of /opt/local/bin verfied that there was no longer a ruby or gem or update_rubygems command left.

Of course I left out the part where I removed all of the manually installed gems under /opt/local/lib/ruby/1.8/rubygems by "rm -fr / opt/local/lib/ruby/1.8/rubygems". Don't quote me on that path as I am writing this post on my iPhone and recalling it from memory. I only know the path because I also reinstalled rubygems manually before I figured out what the real problem was. I would probably have missed the real problem if I hadn't installed rubygems with "ruby setup.rb" after downloading it. The install commands showed RubyGems beings installed to /opt/local/... I had to remove that copy of RubyGems manually. Which wasn't so hard. All the install commands with the full paths of the installed files were still in my scrollback buffer.

I also didn't mention that I had uninstalled all my gem packages from the Leopard side of things. Including the original packages under /System. Luckily one of the articles I'd googled had the complete list. It was easy enough to do a "gem install rails sqlite-ruby capistrano mongrel libxml-ruby ruby-openid ruby-yadis rubynode RedCloth sources ferret acts_as_ferret fcgi termios cgi_multipart_eof_fix daemons dnssd gem_plugin hpricot needle actionwebservice activesupport". The full list of preinstalled gem packages is available here. I abbreviated my gem install command to only include what is necessary as installing rails pulls in some of the other packages in the list like activerecord and rake.
Everything worked like a charm after that. Now on to writing that SFA app. After that I'll have to get back to my holy war to remove redundant MacPorts packages. I think I was up to removing those two verions of Python 2.4 and 2.5. Seeing as how Leopard ships with 2.5 and 2.4 was a buggy beast at best when compared to the speed and bug fixes of version 2.5.