Shell Hacks and Examples
I am a fan of the command line. What it really comes down to is efficiency.
I'm the type of guy who would rather spend an hour learning to use a tool that
will automate a task than make a thousand "easy to use" but tedious clicks in a
GUI. Naturally, GUI's have their place, but I generally prefer command line
methods. They're so much more versatile.
At my job as a Sys Admin, I once had to help someone who had a problem where
Photoshop for Windows saved a bunch of images but refused to re-open them.
Other programs could open them just fine, and once you resaved the files,
Photoshop wouldn't have any problem at all. I described my diagnosis of the
problem to the user and explained that we should open and save the dozen or so
files using another program. At my Linux box, with the user looking over my
shoulder, I su'd to them, went to their home directory, and then did something
like the following: "mkdir bad; mv *.jpg bad; cd bad" and then "for i in *.jpg;
do convert $i ../$i; done". Two seconds later, I told them that everything
should be working now, and they said, "What? You didn't do anything." That's
how I felt, too. It's a good feeling.
So here you'll find a bunch of one or two liners that I consider either
essential or very cool. My examples and descriptions are meant to convey the
gist of the technique. If you research the tools used here, you should be able
to adapt the examples to many other applications.
SSH
- SSH-ing with another environment
- Say you want to be able to type "work" and ssh to remotehost with a
slightly different environment than normal. In this example we'll assume you
want to cd to /var/www/html/abcd/efgh/ijkl automatically. Create a file on
remotehost named .bashrc-work and add ". $HOME/.bashrc" and "cd
/var/www/html/abcd/efgh/ijkl" to it. Then, on localhost add the following line
to your .bashrc: 'alias work="ssh -t remotehost bash --rcfile .bashrc-work"'.
Now, whenever you type "work" on localhost you'll ssh into remotehost and
automatically find yourself in your special directory. Of course this idea can
be adapted to do anything automatically on login.
- ssh -X remotehost
- Connect to remotehost and tunnel all X traffic over the encrypted
connection. To see how this works, run the above command, and then run
"xeyes" when you get your shell prompt on the other machine. Notice how it
automatically displays on your own X server. I think this should be common
knowledge, but it never hurts to give a reminder. Note that if you get an
error message like "Gdk-ERROR **: BadWindow (invalid Window parameter) serial
3945 error_code 3 request_code 38 minor_code 0 Gdk-ERROR **: BadAccess
(attempt to access private resource denied) serial 3946 error_code 10
request_code 102 minor_code 0" then you should instead use "ssh -Y".
- Tunnelling an entire X Session over SSH
- Run "ssh -X remotehost" as described above. Now run "gdmXnest &" and
then run "export DISPLAY=:20" where "DISPLAY=:20" should be the same thing that
gdmXnest just printed. Now run "gnome-session" or "startkde" or whatever you
do to run your X Session ("/etc/X11/xdm/Xsession" will do your .xsession file).
Note that if you aren't on the same LAN, you'll probably want to use a
lightweight window manager.
- Email over SSH
- I used to do all of my email over a cool but dirty hack. Both incoming
and outgoing email go over an SSH Tunnel. Here's some information I wrote up
about doing Email over an SSH Tunnel.
Tar
- (cd /orig/dir; tar cf - .) | (cd /targ/dir; tar xpf -)
- Copying with a cp -R will mangle stuff sometimes. If you want to
completely copy a tree, this command is the best way to do it. Additional tar
options, like --same-owner, will let you keep things even more intact. Another
way to do this is: "tar cfC - /orig/dir . |tar xpfC - /targ/dir". They should
both do exactly the same thing, though the original example is perhaps a little
easier to remember.
- tar cf - . |ssh remotehost "cd /targ/dir; tar xf -"
- This is logically exactly the same as the tar pipe above, except that this
time ssh allows our pipe to cross system boundaries.
- find . -type f -name \*.png |tar cvTf - tarfile.tar
- Use find to specify exactly which files you want to include in your tar
file. This example grabs all png files in the current directory and its
subdirectories and throws them into tarfile.tar. You can give very complex
criteria (see the man page for find). If tar gets a directory it will tar up
everything under it, so make sure to specify "-type f" or at least "! -type d",
unless you're actually wanting to include whole subdirectories.
Find
find . [expression] -printf "mail -s subject hello@xyz.com >%p\n" |bash -s
Find's -exec commands are great but they're limited to what you can do with
an exec system call. That means: no pipes, no redirects, no expressions, etc.
With this example, you can put absolutely anything that bash understands,
including complex loops and expressions, inside the quotes, and Bash will run
it as a shell script. Things to remember: %p will be substituted by the
filename found (man find for the other dozens of substitutions). Also, you
need that trailing '\n' or a semicolon, or bash won't be able to separate your
statements. Have fun.
Miscellaneous
kill -9 `ps -ef |grep something |cut -c 10-15`
Kill everything that matches a regular expression you give it. This is
much nicer than typing in numbers manually.
watch "mailq |head -1"
Watch will run a command every few seconds, so you can see when the status
of something changes. This example watches the state of the mail queue. When
you're waiting for DHCP, "watch ifconfig eth0" is very cool.
du -k |sort -n |tail -30
See which files and directories are using the most space. This is way
cooler than a normal du -sk or du -sh.
for old in `ls *.jpg`; do new=`basename $old .jpg`-thumb.jpg; convert
-size 200x200 -resize 200x200 $old $new; done
Use ImageMagick to create a bunch of thumbnail images with a maximum width
of 200 pixels and a maximum height of 200 pixels (though the ratio will be
preserved). It will run on all files *.jpg and will make hello-thumb.jpg from
hello.jpg.