Many Unix users may be familiar with ClusterSSH. This tool allows you to open up ssh terminal sessions to many hosts (like when administering a cluster), and then send commands to all of the connected machines simultaneously. csshX is a free, open source tool inspired by ClusterSSH, but designed to work with the OS X Terminal.app (rather than X11's xterm). Once downloaded, the csshX script can be run where it is, or copied into /usr/local/bin/ (or any other directory on your path) for convenience.
The basic command line is:
csshX hostname1 hostname2 hostname3 [...]
This will open three Terminal windows, and ssh into hostname1, hostname2, and hostname3, connecting to one host per window. A fourth (red colored) controller Terminal window will also be opened (this screenshot demonstrates how things look). Any commands typed into the controller window will be sent to all three hosts. You can also send commands directly to only one of the host terminals by selecting its window directly.
For advanced use, menus can be brought up by pressing Control-A. These menus provide you with options such as disabling/enabling input to individual windows, minimizing all the windows, retiling the windows, etc.
[robg adds: This worked as described in testing with my, um, two-machine cluster, and I can see how this would be very useful for those working with a larger number of machines.]
"A little knowledge is a dangerous thing" as they say. A long story for a problem people may rarely if ever encounter, but here goes:
I love TextWrangler for editing all kinds of text files. I set it to save in UTF-8 (with the initial byte order mark, or BOM) set by default. I discovered that the BOM makes Safari read HTML as Unicode automatically, without the need for a charset declaration, or messy entity codes for special characters. So now I can just type HTML freely in any languages and scripts I want.
Now over to Terminal: On my old Mac, I had a few default aliases set up for tcsh. I learned that now in Leopard the default shell is bash, which I am happy to note supports Unicode in pathnames seamlessly, but which uses a very different structure for keeping default aliases. I found my old ~/Library » init » tcsh » aliases.mine file and did my research: I copied the file, saved it as ~/.bash_alias, and created ~/.bash_profile to source it.
But nothing would work. I got the strangest errors, like -bash: source: command not found. Say what?! The command is right there in /usr/bin/ where it belongs! I dug for answers on the net for hours, and kept trying things. Eventually I noticed that when I executed ~/.bash_alias myself on the command line, all but the first of my aliases loaded. When I changed the file to start with a blank line, all aliases loaded, with one error about an empty command. Ahha! So the problem turned out to be the file format: the BOM made the first word of the first line into nonsense. So I resaved both of my dot-files in "UTF-8, no BOM" mode, and all is well.
As a Linux SysAdmin, of course my favorite desktop is OS X! On my MacBook Pro, I run CentOS using VMware. In my work, every day I use a fantastic technique called SSH Bouncing, both from within the VMware Linux environment and from Terminal on the Mac itself.
Explained in simple terms, assume you're on a computer, A, and you want to ssh into a computer (say, C) that is isolated from the world on a private network. If a computer B exists (and you already have an account on it) that has two network interfaces, one facing the internet (or at least the network you're on) and the other facing the private network, SSH Bouncing let's you ssh directly from computer A to computer C in one jump, with no added software or weakening of your security setup, as it requires the already-existing account on computer B.
This greatly simplifies file transfer, since you don't have to do the two step "SSH Hopping" of A » B, B » C. And popping a graphical X-Window off of C » A isn't possible at all without this technique. See this article for all the technical details on setting this up. It's very straightforward, and you'll need to understand it first for this hint to be useful.
Anyway, the point of this hint is that I used this all the time under Tiger, and when I upgraded my home and work Macs to Leopard, this broke. Specifically Mac » Mac » (destination) bouncing broke. I kept getting "Connection closed by remote host" errors.
With today's increased Flash storage sizes, there may not be many times when you need to split files. However, when you do need to do so, I find that tar is a good tool (this hint is also good if you want to split an archive before burning to DVDs).
The following use of bash's brace expansion makes creating multi-volume tar files easy. To create a multi-file archive of a given length, use this:
tar --tape-length=102400 -cMv --file=tar_archive.{tar,tar-{2..100}} [files to tar]
To extract from the archive:
tar -xMv --file=tar_archive.{tar,tar-{2..100}} [files to extract]
To create DVD-sized volumes, use --tape-length=4588544. In the above examples, replace [files to tar] and [files to extract] with the location(s) of the file(s) you wish to segment.
There are (or have been) a number of version control systems en vogue over time -- CVS, SVN, Git, etc. I try to keep up with them and use them where possible, but I don't put everything I do in version control. Since I am on a Mac running Leopard, I do have (and use) Time Machine. So I wanted to see if I could use my Time Machine backups to do some quick comparisons between source files.
The result is the following quick and dirty python script. Note that you can find the original version of this script in this post on my blog; you may want to check there for an updated version. Here's the code:
In the unlikely event that I ever have time, this would be a cool pyObjC project -- add a file browser panel, date versions picker, and a webkit view (with some better CSS).
[robg adds: To use this script, save the file (filecomp.py or whatever), make it executable (chmod a+x filecomp.py), and then run it in Terminal, passing the path to a text file as an argument. Assuming you saved it somewhere on your path, that would look something like: filecomp.py ~/Documents/myfile.txt. It seemed to work in my testing, though thanks to a recent mistake on my part, I don't have much Time Machine history to dig through.]
It appears that if you have used CPAN to augment your default Perl installation, then Security Update 2009-001 "kills" Perl, so your scripts won't run. There is a more discussion about this in this Apple Discussions thread.
The fix mentioned in that thread that worked for me was the following, all done in Terminal:
$ mkdir -p /SourceCache
$ cd /SourceCache
$ curl -O http://cpan.mirror.solnet.ch/authors/id/G/GB/GBARR/IO-1.2301.tar.gz
$ tar xzf IO-1.2301.tar.gz
$ cd IO-1.2301
$ perl Makefile.PL
$ make
$ make install
Note that for some of the above commands, you must be logged in as root, or run using sudo.
[robg adds: According to the linked discussion, only those who have updated certain core Perl modules via CPAN will have this problem. In this post (linked in the above discussion), the author states more specifically that the problem is that "the Security Update brings (old) IO.bundle with version 1.22, but your IO.pm has been updated to the latest 1.23 on CPAN shell." The author mentions you may have to make similar fixes to the Scalar::Util and Storable modules. I haven't tested this one.]
I searched far and wide, but only found third party utility references (an app called cscreen, for one) to get the current display layout programmatically in a script (AppleScript / bash). This could be easily munged into AppleScript, but here's what I came up with for a bash function that output something like:
Display Unit: 0 with height 900 and width 1440 is positioned at (0, 0)
Display Unit: 1 with height 1024 and width 1280 is positioned at (503, -1024)
However, you can massage the output to suit your needs. The script only returns the last set-up displays. In other words, if a display is hot-unplugged, the script will still report the last layout set in System Preferences.
Here's the script; it's only been tested on 10.5.6:
[robg adds: To use the script, copy and paste the above into vi, emacs, BBEdit, TextEdit, or other pure-text editor. Save the file with a meaningful name (screeninfo). Then, in Terminal, cd to the directory where you saved the file, and run this command to make the file executable: chmod a+x screeninfo. You can then run the script (assuming it's been saved somewhere on your path) by typing screeninfo (or from within the current directory with ./screeninfo). It worked fine on my dual-monitor setup.]
I have tons of radio show recordings, which all automatically have the date they were recorded in the filename, as so:
Reelin and Rockin with Z and D -[2008-10-18].mp3. However, for a podcast, I want the actual creation/modification date to reflect the date of the show. Unfortunately, whenever I actually get around to editing the audio (to cut out previous/following DJs), the date does not reflect the date it was recorded.
I now have 50 or so files with the incorrect dates, and would like this to be automatic at some point anyway. So I figured out how to write a Bash shell script (which can be run via an Automator plug-in) to set the dates correctly using the filename. So now I can just Control-click on the files and choose the script from the Automator section of the contextual menu. (And now I can tweak it to use as a Folder Action, to run automatically when I save the edited audio file!)
Here's the shell script:
for f in "$@"
do
if [ -n "$f" ]; then
fullpath=$f
else
echo "No filename specified"
echo "Usage: KCSB-SetDate <filename>"
fi
fname=`basename "${fullpath}"`
year=`echo $fname | cat | awk -F - '{print $2}' | awk -F [ '{print $2}'`
month=`echo $fname | cat | awk -F - '{print $3}'`
day=`echo $fname | cat | awk -F - '{print $4}' | awk -F ] '{print $1}'`
fulltime="${year}${month}${day}0000"
touch -t "$fulltime" "${fullpath}"
done
The automator action is:
Finder: Get selected Finder items
Automator: Run Shell Script with 'Shell' set to bash, and 'Pass input' set to as arguments, and the code itself as shown above (replace any existing code in the script box with the code from above).
I then saved this as a Plug-In for Finder. To make it a bash shell script instead, remove the for/do/done loop, and change $f to $1 (for files as arguments)
Other things I had to learn to get this working:
The awk pipes: the -F option lets you specify a delimiter/separator, and so -F - makes a dash (-) the separator (with the backslash to make sure bash doesn't try to interpret it, just in case). Then the {print $n} commands to awk make awk print out the nth string, if each string were separated by the - delimeter we specified.
To debug a shell script from within Automator, you must add the View Results object at the end, so you can see the results of echos and outputs etc.
Quite often when reading macosxhints, I read a hint that involves a terminal command, usually a defaults write hidden preferences trick. The easiest way to enter these commands is to copy them from Safari, and paste them on to the command line in Terminal. The problem is that most of the time I'm using xterm running under X11, and it doesn't support cut and paste with Aqua.
One can get around this problem by entering the following at the shell prompt.
pbpaste | sh
That's it. pbpaste is a shell command that writes the contents of the clipboard to standard output; piping it into the shell causes the shell to execute the command that was on the clipboard. pbcopy works in the other direction -- text sent to the standard input of pbcopy ends up on the clipboard. For example:
After much frustration, I realized that the shell command pbcopy was destroying non-ASCII characters in an AppleScript that I was trying to write. Although pbcopy is an extremely convenient way to take the standard input and place it on the clipboard, I also needed access to accented characters.
Luckily, I found this blog post that explained everything. The important part was a comment there that explained how to set a default encoding by adding the following line to my .profile file:
While this fixed the problem while working in the Terminal, it did not fix the problem within AppleScript. I did find that I could add the aforementioned export command inside the do shell script, and everything seemed to work as expected. An example is shown below.
do shell script "export __CF_USER_TEXT_ENCODING=0x1F5:0x8000100:0x8000100; cat -s " & quoted form of (fileToCopy) & " | pbcopy"
This has been working great for me, but one of the posts on the blog does claim a problem. The blog author also wrote a replacement for pbcopy and pbpaste that is also supposed to alleviate these issues. I have not yet tried it, however.