The Fugue

Counterpoint by Hans Fugal

sh.vim

Posted by Hans Fugal Sat, 29 Mar 2008 06:38:58 GMT

Have you ever been frustrated with perfectly valid bash syntax being highlighted as incorrect in vim? Like this:


#!/bin/sh
foo=$(ls /tmp)

$() is a perfectly valid, nay preferred substitute for backticks. The problem is that vim is deciding this is pure old bourne shell instead of whatever else we'd like it to be. If you change the shebang to #!/bin/bash and re-edit the file, then the error markings go away. But maybe you're writing for the nebulous POSIX shell, not bash nor sh. Or maybe you just don't care and you don't want vim complaining that you're using bashisms even though your shebang says sh. You can set the defaults so that it reflects your system and preferences. It's all there in :help sh.vim.

no comments |

Pipelining Processes in Ruby

Posted by Hans Fugal Thu, 02 Aug 2007 21:58:00 GMT

I've occasionally needed to pipeline some processes in Ruby, especially when doing sysadmin-type tasks. You can always do:

system "foo | bar"

but that gets interpreted by the shell. That can be a problem when you need to include filenames that could have all kinds of nastiness including spaces, semicolons, exclamation points, etc. You should be shaking in your boots about now.

Well, for single processes, it's easy:

system "foo", arg1, arg2

But if you want to pipe them together it's a bit more difficult. I came up with this solution, and it seems to be working well in my "convert my cool music collection into a lame (wink) format my car stereo can understand" script:

  def pipeline(*args)
    pids, r = args.inject([[],nil]) do |memo, cmd|
      pids, rr = memo
      r,w = IO.pipe
      if (pid = fork)
        pids.push pid
        rr.close if rr
        w.close
        [pids, r]
      else
        r.close
        $stdin.reopen rr if rr
        $stdout.reopen w
        cmd = [cmd] if String === cmd
        exec *cmd
      end
    end
    r.close
    pids.each {|p| Process.waitpid(p)}
  end

  pipeline ['oggdec','-o','-',oldpath],['lame','-',newpath]

Do take the time to figure out what's going on, but don't do it without a piece of paper handy or you might sprain something.

Update

I had an error in the original post—if you don't close rr in the parent of the fork you will end up with too many open files eventually.

Posted in | 2 comments |

Xsession and .bash_profile

Posted by Hans Fugal Sat, 22 Jul 2006 19:19:34 GMT

Once upon a time I fought the good battle trying to get one of [gkwx]dm to run a login shell, because you know, we're logging in. I wanted it to run a login shell so I could run keychain or something.

Well today I wanted to figure out how to keep startx from running keychain. It shouldn't have been running keychain because keychain runs from .bash_profile which shouldn't be sourced for two good reasons: A) it's not a login shell (this is a boot script to start freevo), and B) it's not bash, it's /bin/sh (yes, I know that's really bash but when invoked as sh it doesn't source .bash_profile).

It turns out some bright kid created /etc/X11/Xsession.d/91source_profile (I think that's what it was called), that sourced every profile file it could think of whenever Xsession was run. This is both bad and stupid. It's bad because sometimes an X session is not a login. It's stupid because they could have achieved the same thing in a more elegant way by adding --login to the shebang line of /etc/X11/Xsession. The place to do login shell stuff is where you actually log in, i.e. [xgkw]dm, not Xsession.

Please, my friends, if you go out into the world and work on something that involves login and environment, read the manpages and understand what a login shell, an interactive shell, and a noninteractive nonlogin shell are and when you want each. Thanks. End of rant.

Posted in | no comments |