perl and general scripting hackery

Some new tmux tricks (for me)

December 9, 2023 perl and general scripting hackery , ,

I’ve been using tmux since RHEL stopped shipping screen by default.  We now use Oracle Linux at work, not RHEL, and perhaps Oracle Linux ships screen, but I’m unlikely to switch back now.

I blundered upon a tmux book at the Toronto Public Library today.  It’s a little book, and most of what is interesting looking to me, is in the first couple chapters.  Here are some notes.

tmux sessions.

I normally want just one tmux session per machine, but tmux does have the capability of creating named sessions. I knew this, but hadn’t used it, and it’s spelled out nicely in the book.  Here are two bash aliases to exploit that feature:

alias tplay='tmux new -s play'
alias twork='tmux new -s work'

Here are two such sessions in action:

Notice the little [work] and [play] indicators in the bottom left corner of each screen session.  Nice!

Of course, I created a couple aliases to attach to my named sessions:

alias atplay='tmux at -t play'
alias atwork='tmux at -t work'

tmux window switching “menu”

The only thing screen feature that I miss is the menu of windows for the session, but I’ve gotten used to that limitation.

However, because tmux shows the active sessions at the bottom, you can use that as an built in session switching mechanism.

Do this with [Prefix] N, where N is the window number.  [Prefix] is the notation from the book that has the control sequence used for shortcuts.  For me, because I have this in my .tmux.conf

unbind C-b
set -g prefix ^N
bind n send-prefix

For me, [Prefix] is control-n (I don’t remember why I had ‘set -g’ and bind, which looks redundant to me.) So, I can do window switching with

control-n 1
control-n 2

Most of the time I use my F5, and F8 commmand key mappings to do window switching

bind-key -T root F5 select-window -p
bind-key -T root F6 select-window -l
bind-key -T root F8 select-window -n
bind-key -T root F9 new-window

but this ‘[Prefix] N’ gives me another way to do window switching.

However, what do you know, there is an equivalent to the old screen window selection mechanism, as I’ve just learned from the book:

[Prefix] w

This window switcher is actually really cool. It shows a preview of the window to be selected, and even shows the windows in both named sessions, so not only is it a window switcher, but also a session switcher!

Panes

I’d seen that tmux has support for window splitting, but have never used it.

Here are the commands, for new vertical split, new horizontal split, pane cycle, and pane navigate:

[Prefix] %

[Prefix] ”

[Prefix] o

[Prefix] Up-Arrow,Down-Arrow,Left-Arrow,Right-Arrow

Looks like the pane splitting is specific to the active window, so if you do a split pane, and have run a rename-window command, for example, using something like:

alias tre='tmux rename-window'
function tnd
{ 
    tmux rename-window `pwd | sed 's,.*/,,'`
}

then the split pane only shows up in that named window, like so:

Some random tricks

Detach: [Prefix] d

(I use command line ‘tmux det’)

Switch between horizontal and vertical panes: [Prefix] space

Create new window: [Prefix] c

(I use my F9 bind-key mapping)

 

Pane mapping bind-keys for adjusting window size:

tmux bind -r H resize-pane -L 5
tmux bind -r J resize-pane -D 5
tmux bind -r K resize-pane -U 5
tmux bind -r L resize-pane -R 5

(can also be put into the .tmux.conf without the leading tmux)

This allows you to resize panes. For example, perhaps you want to tail the output of something long running, or run top, or something else, but have the rest of the upper pane in action, something like:

Switching from screen to tmux

January 11, 2021 perl and general scripting hackery , ,

RHEL8 (Redhat enterprise Linux 8) has dropped support for my old friend screen.  I had found a package somewhere that still worked for one new RHEL8 installation, but didn’t record where, and the version I installed on my most recently upgraded machine is crashing horribly.

Screen

Screen was originally recommended to me by Sam Bortman when I worked at IBM, and I am forever grateful to him, as it has been a godsend over the years.  The basic idea is that you have have a single terminal session that not only saves all state, but also allows you to have multiple terminal “tabs” all controlled by that single master session.  Since then, I no longer use nohup, and no longer try to run many background jobs anymore.  Both attempting to background or nohup a job can be problematic, as there are a suprising number of tools and scripts that expect an active terminal.  As well as the multiplexing functionality, running screen ensures that if you loose your network connection, or switch from wired to wireless and back, or go home or go to work, in all cases, you can resume your work where you left it.

A typical session looks something like the following:

i.e. plain old terminal, but three little “tabs” at the bottom, each representing a different shell on the same machine.  In this case, I have my ovpn client running in window 0, am in my Tests/scripts/ directory in window 1, and have ‘git log –graph –decorate’ running in window 2.  The second screenshot above shows the screen menu, listing all the different active windows.

screen can do window splitting vertically and horizontally too, but I’ve never used that.  My needs are pretty simple:

  • multiple windows, each with a different shell,
  • an easy way to tab between the windows,
  • an easy way to start a new shell.

I always found the screen key bindings to be somewhat cumbersome (example: control-A ” to start the window menu), and it didn’t take me long before I’d constructed a standard .screenrc for myself with a couple handy key bindings:

  • F4: window menu
  • F5: -1th window
  • F6: previous window (after switching explicitly using key bindings or the menu)
  • F8: +1th window
  • F9: new window

I’ve used those key bindings for so many years that I feel lost without them!

With screen crashing on my constantly, my options were to find a stable package somewhere, build it myself (which I used to do all the time at IBM when I had to work on many Unix platforms simultaneously), or bite the bullet and see what it would take to switch to tmux.

tmux attach

I chose the latter, and with the help of some tutorials, it was pretty easy to make the switch to tmux.  Startup is pretty easy:

tmux

(instead of screen -q)

and

tmux at

(at is short for attach, what to use instead of screen -dr)

tmux bindings

All my trusty key bindings were easy to reimplement, requiring the following in my .tmux.conf:

bind-key -T root F4 list-windows
bind-key -T root F5 select-window -p
bind-key -T root F6 select-window -l
bind-key -T root F8 select-window -n
bind-key -T root F9 new-window

tmux command line

One of the nice things about tmux is that you don’t need a whole bunch of complex key bindings that are hard to remember, as you can do it all on the command line from within any tmux slave window. This means that you can also alias your tmux commands easily! Here are a couple examples:

alias weekly='tmux new-window -c ~/weeklyreports/01 -n weekly -t 1'
alias master='tmux new-window -n master -c ~/master'
alias tests='tmux new-window -n tests -c ~/Tests'

These new-window aliases change the name displayed in the bottom bar, and open a new terminal in a set of specific directories.

The UI is pretty much identical, and a session might look something like:

tmux prefix binding

The only other customization that I made to tmux was to override the default key binding, as tmux uses control-b instead of screen’s control-a. control-b is much easier to type than control-a, but messes up paging in vim, so I’ve reset it to control-n using:

unbind C-b
set -g prefix ^N
bind n send-prefix

With this, the rename window command becomes ‘control-n ,’.

I can’t think of anything that uses control-n, but if that choice ends up being intrusive, I’ll probably just unbind control-b and not bother with a prefix binding, since tmux has the full functioning command line options, and I can use easier to remember (or lookup) aliases.

Incompatibilities.

It looks like the bindings that I used above are valid with RHEL8 tmux-2.7, but not with RHEL7’s tmux-1.8.  That’s a bit of a pain, and means that I’ll have to

  1. find alternate newer tmux packages for RHEL7, or
  2. figure out how to do the same bindings with tmux-1.8 and have different dot files, or
  3. keep on using screen until I’ve managed to upgrade all my machines to RHEL8.

Nothing is ever easy;)

A really dumb DNS lookup for my internal network

March 8, 2017 perl and general scripting hackery , , , , ,

The new Hitron cable modem in the house cowardly refuses to let me cache mac and ip address pairs, which is really annoying because my ip addresses now change on me over a couple days. The old router (also a Hitron) allowed that, so putting it on a UPS was generally enough to let me have a static IP table, provided I didn’t have to reboot it.

Here’s a hack using nmap that I just cobbled together to fill in the /etc/hosts entries on the couple machines that I want to talk to each other (mac and Linux machines, so all are unix like).

my %hostnameByMacAddr = (
'B8:4E:3F:C4:04:02' => 'router',
'E4:5C:89:C2:0F:4B' => 'macbookw # wireless',
'10:C2:C6:A0:20:58' => 'nuc2w',
'10:C2:C6:CA:93:6A' => 'nuc1w',
'A8:AE:ED:EB:39:86' => 'nuc1',
'A8:AE:ED:7D:CE:5A' => 'nuc2',
'28:C9:86:46:A8:15' => 'macbookt # thunderbolt monitor connected',
'10:24:2B:A1:7B:F7' => 'brother # printer',
'BC:87:A3:34:1A:FF' => 'macbooke # ethernet cable connected',
);

open my $h, "sudo nmap -n -p 22 192.168.0.1/24 2>&1 | grep -e '192' -e '^MAC' |" or die;

my $ip;
while ( <$h> )
{  
   if ( /scan report for.*(192\.\d+\.\d+\.\d+)/ )
   {  
      $ip = $1 ;
   }

   if ( /MAC Address: (.*) / ) {
      my $mac = $1;

      if ( defined $hostnameByMacAddr{$mac} ) {
         print "$ip $hostnameByMacAddr{$mac} # $mac\n" ;
      }
      else {
         print "# $ip $mac # unknown\n" ;
      }
   }
}

close $h or die;

If anybody knows how to set up an actual DNS server for internal networks, I’d be interested to see what is involved, since it looked very hard when I googled it.

Some notes on copying and moving text in vim

April 13, 2015 perl and general scripting hackery , ,

Emad just asked me a vim question (how to use a search expression instead of a line number), and I ended up learning a new vim commmand from him as a side effect.

I’d done stuff like the following before to move text to a new file

:,/Done/-1 !cat > /tmp/newfile.txt

This assumes you’d like to delete everything from the current position to the line just before the /Done/ search expression, and write it into /tmp/newfile.txt.

The mechanism here, is that the selection is filtered through a script, where the output of the script is empty, so the lines are deleted. This particular script has the side effect of creating a file with the selected range of lines. The end effect is that the text is moved.

If you’d like to keep it and copy it to the new file, you can tee instead of cat it:

:,/Done/-1 !tee /tmp/newfile.txt

This is faster than selecting a range, switching buffers copying into the buffer, saving, and switching buffers back.

Emad taught me that this can also be done with the w command, like so:

:,/Done/-1 w /tmp/newfile.txt

It doesn’t surprise me that there’s a faster way to copy text from one file to another than using tee, but since I knew one way, I never went looking for it.

parallelized xargs

March 12, 2015 perl and general scripting hackery

I’ve used xargs before to execute commands long enough that attempting them with backquotes fails. For example, if the list of files ‘c’ is too long, a checkin attempt like:

    cleartool checkin -c 'blah blah blah' `cat c`

could generate an “environment too long” error in the shell. Something like:

    cat c | xargs cleartool checkin -c 'blah blah blah'

is equivalent. This also checks in one file at a time, using all the filenames in the file ‘c’, but allows xargs to farm out the commands one at a time without building one giant execv argument. What I didn’t know was xargs has a parallelization option:

    cat c | xargs -P 8 -n 1 cleartool checkin -c 'blah blah blah'

This does the same job, with -n 1 restricting xargs to passing one file at a time (which may not be necessary in this case), but starting 8 different processes for the work!