Send Remote Commands Via SSH

This is one of those "I'm posting it so I remember, 'cause I keep forgetting" posts. It's also astoundingly cool, though, if you didn't know about it. Which I didn't until fairly recently.

If you've ever wanted to send a command to a remote computer without ever actually logging in to that computer, ssh is your friend. Yes, with ssh you can send commands directly to another system. Who knew?

I'll keep this short and sweet. Here are some examples.

The basic form looks something like this:

ssh systemsboy@rhost.systemsboy.edu 'ls -l'

where "systemsboy" is actually your username on the remote host, and "rhost.systemsboy.edu" is your remote system. The command you're sending is contained in single quotes.

Here is an example sending multiple commands:

ssh systemsboy@rhost.systemsboy.edu 'ls -l; ps -aux; whoami'

wherein each command is separated by a semicolon.

Finally, here is an example sending a command that requires user interaction:

ssh -t systemsboy@rhost.systemsboy.edu 'top'

Note the -t flag. That tells ssh that you'll be interacting with remote shell. Without the -t flag top will return results after which ssh will log you out of the remote host immediately. With the -t flag, ssh keeps you logged in until you exit the interactive command. The -t flag can be used with most interactive commands, including text editors like pico and vi.

Sending remote commands via ssh is incredibly handy when writing shell scripts as it allows you to run your scripts locally even if those scripts are meant to effect changes on a remote machine. I just wrote a script, for instance, that sets up vacation mail forwarding for staff members. Without these remote commands I would have had to have staff members log directly onto the mail server and run the scripts from the command line, which I don't think they'd be too happy about. With ssh remote commands, I can give them the scripts and they can run them right from their Desktops. Believe me, they much prefer this.

Credit where due, all information was obtained from Rambo's post. Rambo, thanks. Whoever you are.

UPDATE:

For additional information about using this trick with variables within the remote command, see "Using SSH to Send Variables in Scripts."

Scripting Filenames with Spaces: A for Replacement

Okay, this will be a quickie. Really.

I use for loops in scripts all the time, but for chokes on files with spaces in the name. After years of finding ways to avoid this problem any way I could, I've finally found what I believe to be the solution.

The for command treats any whitespace as a line break. So if you try to use for on a list of files (or folders or whatever) the loop will not function properly on items with spaces in the name. The for command will treat everything after the space as a new item.

Let's say you want to copy every file that starts with "Systems" in the folder "Start" to a folder called "Finish." The "Start" folder contains the items:

Systems Boy

Systems Girl

Systems Baby

James Bond

Bat Man

Using for would go something like this:

for item in `ls Start | grep Systems`

   do cp "$item" Finish

done

The for command, however, will treat "Systems" and "Boy" as two separate items, and when the cp command is issued it will complain:

cp: Systems: No such file or directory

cp: Baby: No such file or directory

cp: Systems: No such file or directory

cp: Boy: No such file or directory

cp: Systems: No such file or directory

cp: Girl: No such file or directory

The solution is to forego for and pipe your command to a while read statement like in the following example:

ls Start | grep Systems | while read item

   do cp "$item" Finish

done

The quotes around the $item variable are essential. Without them the script will fail in the same way as for. With them, the script works like you wish the for loop did and is able to properly copy files with spaces in the names.

Nice. And by "nice" I mean halle-fuckin-lujah!

I should give some credit for this tip. I originally read about it here at MacGeekery, but didn't quite understand it until I read some posts on various forums. Of course, there's nothing like a real-world problem to solve, and I had this as well to aid my understanding of this method.

Scripts Part 5: New Spotlight Disabler

Someone recently commented that my script to disable Spotlight was no longer functioning in v. 10.4.5 of Tiger. When I went to check on the functionality of the old script, I realized I'd been working on a new and improved version awhile back, and that I'd intended to post it, but completely forgot to. So I went in and finished up this spiffy new version, and I'm posting it today for anyone who's interested, or for anyone for whom the previous version had stopped working.

This new version comes with the same disclaimers as the other one (which are now listed in the script itself), but gives you a few more options for disabling Spotlight. In particular, you can now choose to disable/enable Spotlight on either a single volume, or an all volumes. The script will also report the Spotlight status of all currently mounted volumes before asking you what you want to do.

Enjoy!

SpotlightEnableDisable Script
See the code

Scripts Part 4: Cloning — What's the Big Deal?

Boy, there sure are a lot of cloning apps out there. The mother of them all, of course, is Mike Bombich's Carbon Copy Cloner, but it's slowly losing mindshare to more aggressively marketed apps like the affable SuperDuper!. There are others, but I don't feel like scouring the web for them, nor do I feel like going to the effort of linking to them all. Suffice to say, there are plenty. Just search VersionTracker and you'll see.

I find the recent upswing in cloning utilities strange. Apple's bundled Disk Utility application has actually harbored the ability to clone a system disk for some time now (I believe as far back as Panther). And yet, it seems the easier cloning gets, the more apps there are with which to do it. And charge you for it.

Today's script uses a handy command-line utility that's actually been around since the Classic Mac OS days (though not, obviously, in command-line form): asr, which stands for Apple Software Restore. The asr command is essentially a command for cloning disks. In fact, that's exactly what it is. When Mac OS X first came out, asr was not bundled. But in recent incarnations of the OS it's hung around in the command-line, and it's actually gotten quite refined and easy to use. Want to clone your boot drive? Here's the command:

sudo asr -source [source_volume ] -target [target_volume ]

That's it. I can't imagine an easier command structure. In a way, it's almost easier to use than GUI apps that do the same thing. Of course you can get into some very complicated uses of asr, but for basic disk-to-disk cloning it's drop-dead simple.

Now there is one little, tiny bump in this road. Tiger, you see, has a brand spanking new way of making certain files on your boot drive invisible. You know, files like var and etc and private. And Tiger's version of asr (as well as Tiger's Disk Utility program) are none the wiser. So, if you want things set up properly, you need to explicitly set the visibility of these files. There are a few ways to do this. Today's script will use a utility called SetHidden, which comes on the Tiger install disc (a la this Apple KB article). Just so you know.

So here it is. A very simple script for making an exact clone of a volume to another volume. Please keep in mind, because of the file visibility issue, this script MUST be run from the disc image, or it will not work properly. Also keep in mind that cloning will overwrite, replace or even erase the target drive. I am in no way responsible for any damage you incur to your system with this script. If you don't feel comfortable using it, please don't.

That said, here's your free cloning utility.

Download ASRClone

Delayed ACK Startup Item for Intel Macs

MacFixit just reported about troubles the new Intel-based Macs are having with network speeds, particularly AFP connections to, of all things, other Macs. The solution, they report, is to set the delayed_ack property to 0. In order for this change to survive a reboot, however, they recommend editing /etc/rc. The problem with this is that, often, edits made to /etc/rc will be overwritten by future updates to Mac OSX. In my experience, such modifications are better handled with a startup item, which is also a lot easier to add and remove. So I've suggested as much to the fine folks over at MacFixit, and I've even put my money where my mouth is. I'm offering to those who need it this delayedACK Startup Item, hand made by yours truly.

The linked disc image contains the delayedACK Startup Item, and also includes an installer and an uninstaller for the Startup Item.

Enjoy, you lucky Intel Mac owners (of which, alas, I am not one... Yet...)

UPDATE:
A reader called Nubo recently left this comment:

...turning off delayed_ack is not necessarily something that should be left in the startup items forever. Having it on is normally beneficial or at least not severely degrading in normal environments. So this should be reviewed whenever Apple fixes the underlying problem in its implementation, or the actual root cause is found.

Nubo is absolutely right. This startup item should be removed — either by running the included uninstaller or by simply dragging the startup item to the trash — once the problem has been resolved by Apple.

Thanks, Nubo, for pointing this out.

Download the Delayed ACK Startup Item