I was recently trying to do some simple shell scripting with the command httpd -t, which runs a syntax check on the Apache configuration files. If everything is OK, it returns Syntax OK, otherwise, it will try to tell you what's wrong with the files. I wanted to grab the output of the syntax check and display it in my script, but wasn't having any luck -- any attempt to redirect the output, or assign it to a variable, resulted in nothing (empty variable, empty file, etc.). Unix wizards can stop reading this hint now, for I'm sure you know what the problem is...
After much Googling, I discovered that some Unix commands create their output by writing to standard error (STDERR) instead of standard output (the Terminal window, typically). As a result, operations that capture standard output won't work for these types of messages, even though the message itself is displayed in the Terminal window. I found the solution in the Wikipedia entry for stderr: append 2>&1 to the end of the command (note that this is for sh-style shells, including bash, the OS X default shell). This redirects standard error to the same destination as standard output, meaning the data can then be captured as you wish. To put the output of httpd -t onto the clipboard, for instance, you could use this:
$ httpd -t 2>&1 | pbcopy
Or if you wished to assign the output to a variable for use in a script:
CONFIGTEST=`httpd -t 2>&1`
I'm sure there are a number of other commands that output via standard error -- one for certain is ssh -V, which returns the version information for ssh.
My iMac is behind a satellite internet connection, which is very slow. Rather than using Screen Sharing or Finder's file sharing for Back to My Mac, I often find it easier to use ssh. Until today I didn't know how to connect to a Back To My Mac computer via ssh. It turns out that it's very easy:
ssh -vvv -p 22 hostname.username.members.mac.com.
Where hostname is the name you gave to the machine (i.e. the name that appears in Finder), and username is your .Mac username (i.e. if your email address is firstname.lastname@example.org, your .Mac username is steve). Note that there is a "." at the very end of the command -- I've had more consistent success using it that way. You can also try Terminal.app » Shell » New Remote Connection (or press Command-Shift-K) and then look under 'Secure Shell (ssh) for "Discovered Servers"'.
As with all things Back To My Mac related, success is flakey and your best bet is if you have Airport Extreme base stations on both the local and remote machines.
If you have ever used the locate command within Terminal to find a file of yours that, for instance, ends in .doc, you might find that you end up with more than 60,000 hits on your system that you didn't create, and didn't want to know about. Hence, it may be beneficial to create a user-level database for locate that searches only your local directory structure, so that you only see what belongs to you.
To do this, and have my new database updated automatically, I modified a copy of the locate database update program that came with the Mac, set up a crontab to update this database hourly, and then created an alias for my local locate, called llocate. Now when I type llocate .doc , I only find 584 .doc files, and I can rest assured that they are all mine! Read on for the how-to...
I like the way Mac OS X lets you choose any album from iPhoto to use as a set of desktop background images. In particular, using iPhoto albums to create sets of images saves disk space because the same image can be displayed in multiple sets ("albums") even though it's only physically stored on disk just once. I had a number of images that I didn't want to store in iPhoto, but that I did want to use as desktop backgrounds in some sets and that I didn't want to duplicate.
The solution turned out to be to simple but a little tricky. Using the Desktop & Screen Saver System Preferences panel, you can select any arbitrary folder to use for desktop backgrounds. If you fill this folder with Unix symbolic links that all have an absolute POSIX path specified for the link, Desktop & Screen Saver finds and follows each image. However, only symbolic links with an absolute path (or hard links, of course) work. Notably, Mac OS X "aliases" do not work.
So, by way of example, if I have five pictures, 1.jpg through 5.jpg, that I want to display in two sets of background images, set A and set B, I can simply do this in Terminal:
Those commands will have define Set A as containing 1.jpg, 2.jpg, 3.jpg, and 5.jpg, but not 4.jpg. Set B will also contain 1.jpg, 2.jpg, and 5.jpg, but will also contain 4.jpg and not 3.jpg. Just like an album, because we're using Unix links, the re-used images (1, 2, and 5) are only physically stored on disk once, even though they're in both sets of desktop backgrounds.
As I wanted to pass my newsfeeds from Mail.app to a friend I realized that there is no "Export RSS-feeds to ..." button in Mail.app. So I wrote this little workaround to export them in Terminal (assuming the bash default shell):
This exports all URLs from your Mail.app RSS directory directly into the shell. I could then easily pass this list to my friend. As an additional option, here is a little modification to open all feed URLs in the default web browser:
This opens your feeds in the browser with a feed://... URL. Then you can easily add them to your bookmarks bar, or can do something other with them. Note that you may add && sleep 60 after the last bracket if you have lots of feeds in Mail.app.
This will allow you to tab complete any hostname you've previously ssh'd to.
[robg adds: This worked as described for me. The complete command is a built-in bash function that lets you specify lists of options to be used with tab completion on a given command. The version above parses your known_hosts to create the list of options. You can read more about the complete built-in function in the bash man pages -- man bash, then search for the section titled Programmable Completion.]
With the advent of 10.5, MacPorts has had to undergo a lot of updates, some of which have been painfully slow in coming. As a freelance security consultant, I *have* to have TinyCA2 working. Unfortunately, the MacPort project to update it for 10.5 took five months before the trouble ticket was finally even assigned to a maintainer. (I suppose these guys have a lot to do.) So here are some workarounds to make it compile under Leopard:
Edit the files (as root) that are listed in the error output (I had six instances total in four different files) following the command sudo port install tinyca2.
In those files, delete the ' character (apostrophe) mentioned on the line number indicated, which follows the colon in the error output. (If you use nano to edit the files, press Contrl-C to find the current line number.) These are in commented lines, but for some reason, they still keep the files from being processed.
cd to the directory mentioned in the error output (probably /opt » local » var » macports » build » _opt_local_var_macports_sources_rsync.macports.org_release_ports_security_tinyca2 » work » tinyca2-0.7.3 » po) and edit (as root) the language file mentioned in the error output. Change anything not important (ie add a space to the end of the file), then save the file.
Re-run the sudo port install command.
Edit the new language file mentioned in the error output, and do the same thing again (edit, change inconsequential info, save).
After doing this for four or five of the language translation files, the compiling works, and you should now be able to finish compiling the program. Hopefully the great guys at MacPorts can get this port updated, but until they do, this should get you up and running.
The open(1) command (man page) provides a -f option, which open's own help says "Reads input from standard input and opens with TextEdit". But, in fact, you can load the data into nearly any application. Simply combine the -f flag with the -a flag:
curl 'http://example.com/encodingerror.html' | open -a 'Hex Fiend' -f
curl 'http://example.com/example.html' | open -a 'TextMate' -f
curl 'http://example.com/example.png' | open -a 'Preview' -f
curl 'http://example.com/example.m4v' | open -a 'QuickTime Player' -f
Of course, the source of the data doesn't have to be curl; it can be any command. Note that the last two examples aren't even textual data: one is an image, and the other is a video file. You aren't limited to text; any data will work. But there is a catch: open will save the file with a .txt extension, regardless of what kind of data it is (it doesn't look). This could confuse some applications that rely on the filename extension to determine what type of document to open it as. Preview works, but I wouldn't count on any other applications without testing them first.
This hint works in 10.4, and should also work in 10.5. I don't know whether it works in any earlier versions of Mac OS X.
This hint assumes you are using the default bash shell. If you need to run a series of commands interactively as root (or any other user) using sudo, it's most convenient to start a new shell session with the effective user ID you want by typing sudo -s.
Prior to Leopard, you would then get a shell prompt similar to the usual one, but with the effective username in place of your username. For example, if you were logged into host foo.local as user bar, your regular shell prompt would be
...where the ~ represents your home directory (and it will change to show the current directory). If you started a root shell with sudo -s, the prompt would become...
...so you could see at a glance where you were and who you were. Under Leopard, though, the behavior of sudo has changed -- you now get a default prompt with a # to indicate you're running as root -- bash-3.2#. This is much less useful, because now you can't see what host you're logged into or what your working directory is. You have to type extra commands to get that information.
To get back the old-style prompt, you need to set the environment variable SUDO_PS1 in one of your shell initialization files. One way to do this is to start a shell (not a sudo shell) and enter...
...then type Control-C to exit the cat process. Close the Terminal window or tab, open a new one, and start a sudo shell. You should now have the old prompt back. To revert the change, edit the file named .profile in your home directory to remove the line you added above.