Friday, April 01, 2016

tty Types

I have long ago given up on using anything other than GNU Screen as a terminal emulator.  If you're reading this I'm confident you know what both of those things are and why I would need them.  If not, then you work in a different UNIX-y world than I do.  See you next time.

Seriously, though, all of the other emulators I used to use were so fusty and full of so many eccentricities (when compared to everything else I use on a daily basis) that I nearly lost my mind when I realised I could just do this:

# screen /dev/ttyS0 115200

and like actual magic get something with a civilized scrollback buffer, keyboard-centric cut-and-paste from multiple buffers, split-screen, logging, all of the stuff I love about GNU Screen.

But man, there's been one persistent irritation remaining:


That drives me nuts.  If I dare start up vi on some file on one of these, then the terminal gets sufficiently mangled that I'm now reduced to an 80x24 window inside my ridiculously large xterm.  There's no need of that.

In ancient times, you used to be able to create a file named /etc/ttytype where you would create a mapping like this:

screen-256color ttyS0

And that would be interpreted by whatever getty variant you were using and set up your login environment sanely.  That's no longer the case in Debian (and probably no longer the case in most Linux systems today), so I've just been suffering with this until recently.

This is what I've come up with to work around the problem.

# echo <<eot&gt>~/.profile
> TERM=screen-256color
> export TERM
> eval `tset -s`   
> resize
> EOT
# ^D

Then on my next login I get this:


Muuuuch better.

I have resize on most every system I use, so that works for me, but then in my digging around I found this on the Arch wiki:

rsz() {
 if [[ -t 0 && $# -eq 0 ]];then
  local IFS='[;' escape geometry x y
  print -n '\e7\e[r\e[999;999H\e[6n\e8'
  read -sd R escape geometry
  x=${geometry##*;} y=${geometry%%;*}
  if [[ ${COLUMNS} -eq ${x} && ${LINES} -eq ${y} ]];then
   print "${TERM} ${x}x${y}"
  else
   print "${COLUMNS}x${LINES} -> ${x}x${y}"
   stty cols ${x} rows ${y}
  fi
 else
  [[ -n ${commands[repo-elephant]} ]] && repo-elephant || print 'Usage: rsz'  ## Easter egg here :)
 fi
}

I've not used it, but it looks good.  I probably will try it next time I'm on a seriously limited system.

But this is one where I'd like some feedback.  If you've got this far you must have your own solution to this (or you've got a higher pain threshold than I do), so what've you done to solve this problem?

Monday, March 07, 2016

Creating alternatives

Something much bigger I'm probably gearing up to document here (if it works out, since I'm still trying to determine if I've been wasting my time learning this tool or not) inspired me to again check the manpages on a pretty useful little tool:  update-alternatives.

It's nothing terribly special, it gets used everywhere, and it's not very difficult to use, but I don't use it as often as I should, to be honest.

Today I found myself needing to install a new version of ruby on my system.  On an ageing (seriously?  8.2 is ageing?) Debian system like mine that's an interesting level of hell that I'll also get into at a later date not because I ever expect to do that particular dance again nor do I expect anyone else to be interested in it, but because it helped me get the rust out of some gears that I find myself needing to turn reasonably often, so the how is interesting even if the what or why are not.

But back to the quickie for today.

update-alternatives lets you have multiple versions of the same executable (or, to a lesser extent, libraries / manuals / shared files / etc.) installed on a system at the same time and identify the one you want to use by default.  So, for example, I use mutt for email.  But which mutt?

# which mutt
/usr/bin/mutt
# ls -l /usr/bin/mutt
lrwxrwxrwx 1 root 22 Oct 25  2013 /usr/bin/mutt -> /etc/alternatives/mutt*
# update-alternatives --list mutt
/usr/bin/mutt-org
/usr/bin/mutt-patched

So from that you can see that I've got two different versions of mutt, but when I type mutt I get mutt-patched.  If I wanted to change that, though, and run the vanilla mutt.org version of mutt, I could just change the alternative to point at mutt-org instead with a command like:

# update-alternatives --config mutt
There are 2 choices for the alternative mutt (providing /usr/bin/mutt).

  Selection    Path                   Priority   Status
------------------------------------------------------------
* 0            /usr/bin/mutt-patched   60        auto mode
  1            /usr/bin/mutt-org       50        manual mode
  2            /usr/bin/mutt-patched   60        manual mode

Press enter to keep the current choice[*], or type selection number: 
#

That's good, but when I started out today there were no alternatives for ruby. Irritating, since /usr/bin/ruby was already a symlink to one of three (!) versions already installed, but there was no update-alternatives mechanism to switch (and, of course, my new ruby just landed in the same spot and wouldn't actually get used when I invoked ruby --version, so that didn't solve my problem anyway...). It turns out, though, that update-alternatives does exactly the right thing.

# update-alternatives --list ruby  
update-alternatives: error: no alternatives for ruby
# ls -l /usr/bin/ruby*
lrwxrwxrwx 1 root    7 May 10  2015 /usr/bin/ruby -> ruby2.1*
-rwxr-xr-x 1 root 6264 Dec  1  2013 /usr/bin/ruby1.8*
-rwxr-xr-x 1 root 6336 Feb  8  2015 /usr/bin/ruby1.9.1*
-rwxr-xr-x 1 root 6168 Aug 26  2015 /usr/bin/ruby2.1*
# update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby2.1 100
update-alternatives: using /usr/bin/ruby2.1 to provide /usr/bin/ruby (ruby) in auto mode
# update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby1.9.1 50 
# update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby1.8 40  
# update-alternatives --list ruby                                            
/usr/bin/ruby1.8
/usr/bin/ruby1.9.1
/usr/bin/ruby2.1
# update-alternatives --config ruby
There are 3 choices for the alternative ruby (providing /usr/bin/ruby).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /usr/bin/ruby2.1     100       auto mode
  1            /usr/bin/ruby1.8     40        manual mode
  2            /usr/bin/ruby1.9.1   50        manual mode
  3            /usr/bin/ruby2.1     100       manual mode

Press enter to keep the current choice[*], or type selection number: 
#

The numbers I assigned are purely relative, they don't mean anything except that the preferred version will be the one that was previously the direct symlink, the other two stay in place, I can use them by calling them directly or if I need to change my default link to be one of the others it's as simple as using the config option again.  And then I installed version 2.3 and gave it a priority of 110, so it's now my new default.

Easy peasy.

Friday, March 04, 2016

Easy automounting sshfs

I use sshfs a lot.  Mostly because Norton Commander rocked my world when I first encountered it in the summer of 1994 (bear with me).  I was about to say I was done after that, but that's not quite true.  In 1996 I discovered pushd/popd (unfortunately limited to bash at the time) and the staggering power of the Korn shell's history editing and I had nearly everything I needed to be happy with my interface to computers.  Then I found Midnight Commander on one of those Linux Software Archive CDs in late 1996 and the final piece fell into place.

Alright, enough ancient history.  The point of all of this is that when I discovered MC's Virtual Filesystem functionality I didn't think I'd ever need any other remote tool.  Being able to treat FTP connections like local filesystems was mind-blowing.  Then I started getting into SSH and found I could do the same thing with SFTP and later SSHFS connections.  Absolutely outstanding.

It's a shame the method to connect to these Virtual FS systems was such an EMACS-ish combination of hotkeys and things (at least in the early days) that looked nothing like a URI and didn't really seem to follow any sensible pattern.  So I used it less than I otherwise would unless it was something I already had set a bookmark for.  Because reading help sucks and because all too often you'd be hitting F1 for help in MC and instead get some garbage from your desktop environment or window manager.  I know, solvable problems which I've long-since resolved, but back when it really mattered, it was an issue for me.

That brings us to the last, say, two years.  I don't use MC anymore.  At least not very much.  Probably more than half the machines I work with don't even have mc installed anymore.  But I use sshfs all the time because I love the ability to treat remote systems like they are local.

So this is what I've been doing until recently.

# sshfs joe@meathead:/ meathead/
# sshfs pi@retropie:/ retropie/

(Yeah, I'm one of those guys.)

That works pretty well.

Now here's something you're not going to hear out of me very often.  I kind of miss NFS.


Okay, what I actually miss is auto-mounted NFS shares.  This week I started down the path of creating a script to automatically mount my regular SSHFS locations on boot.  That had two obvious problems right out of the gate:
  • Mounts won't come back automatically if the machine reboots
  • Mounts would only happen automatically on boot of my machine
Plus the third, more subtle but still core-to-my-very-being one:
  • Someone else must have already solved this problem
Because that's how I approach nearly every problem.  First assume I'm not the first one to trip over something.

Turns out I was right.

There's a lot of solutions for this particular problem of varying levels of fugly.  This one (specifically the afuse one) documented over at the Arch Wiki turns out to be just the trick:

# afuse -o mount_template='sshfs -o ServerAliveInterval=10 -o reconnect %r:/ %m' \
> -o unmount_template='fusermount -u -z %m' ~/mnt/ssh

So a little bit of that action and now instead of having a bunch of fixed mounts and a clunky script that'll need a bunch of options and checking to see if something's already mounted or whatever, I just dump the above afuse command in my Openbox autostart script and now I can just do this:

# cd ~/mnt/ssh/pi@retropie/

and magic happens.  Initially I thought it would be a bit of a down-side to dedicating a whole directory to afuse, but it turns out I like it a lot better because now I have all of my 'remote' systems in a single hierarchy but I can still treat them like local filesystems for all intents and purposes.  It's pretty sweet.  Should've done this years ago.