やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rubyのシバンについて(shebang)

 コードの先頭に#!/usr/bin/env rubyと書くやつ。

shebang(シバン)

 shebang(シバン、シェバン)とは、ファイルを実行するインタプリタを指定したコードのこと。そのファイル自身の1行目の行頭に#!で始まる。

効果

a.rb

p 'A'

 上記Rubyスクリプトを実行するときは次のようにする。

ruby a.rb

 このとき、シバンを書けばインタプリタrubyを省略できる。

a.rb

#!/usr/bin/env ruby
p 'A'

 実行権限を付与する。

chmod +x a.sh

 以下のようにファイルを指定するだけで実行できるようになる。

./a.sh

シバンは効果的か?

シバンは効果的か?

 シバン書かないほうがよかったのでは?

 ruby a.rb./a.rbにするためにやったことは以下。

  • ファイル先頭にシバンを追加した:#!/usr/bin/env ruby
  • ファイル実行権限を付与した
  • 相対パス./を追加した

 あれ、シバンのほうが作業量もコード量も多くない?

 元々ruby a.rbは文字数としてもrubyとスペース1字しかなかった。そしてシバン実行するときは./が必要である。2文字余分に増えた。つまり差し引き3文字分しか短縮できていない。それだけのためにシバンを追記したり実行権限を付与したわけだ。はたして割りに合っているといえるだろうか。

 しかも後述するが、シバンの動作は環境依存である。

 せめてシバンに複雑な引数が渡せたらよかった。それなら短縮できる効果は高い。だが、それもやはり環境依存だし、$0などの変数も使えないようだ。

 そもそもインタプリタを選別するくらいなら、ほとんどがファイル拡張子でできるのでは? シェルがファイル拡張子から自動で判断してくれたほうが嬉しかった。

語源

sharp bang が短くなって shebang となったそうです。

"shebang"は"Hash Bang"の略。

「#」をハッシュと呼ぶのは元々北米以外の英語圏での慣習

"Bang"は「!」の俗称だ。叩いたり銃を撃ったりしたときの音の擬声語

 私としては以下だと思っていた。

shell bangからという説もある

ユースケース

直接パス指定

#!/bin/bash

 bashスクリプトファイルの先頭を上記のようにする。直接インタプリタbashのフルパスを指定している。

 パスについてはwhichで調べればよい。

> which bash
/bin/bash

 Rubyコマンドについて調べてみた。

> which ruby
/home/{user}/.anyenv/envs/rbenv/shims/ruby

 なので絶対パス指定するとシバンは以下のようになる。

#!/home/{user}/.anyenv/envs/rbenv/shims/ruby

 このパス、完全に環境依存だよね。Linuxディレクトリ構成だし、{user}に至ってはOSのユーザ名だし。anyenvを使って環境構築するとは限らないし。

envによるパス指定

#!/usr/bin/env bash

 envを介してパス指定する。インタプリタ絶対パスはOSによって異なる可能性がある。そこでenvを介することで絶対パス表現を避けている。ただしenvコマンドは絶対パス指定せねばならない。

 Rubyのときは以下。

#!/usr/bin/env ruby

 Wikipediaによると、Rubyのときは以下のほうが良いと書いてあった。

envを用いたトリックはPATH環境変数に依存する。親プロセスが独自にPATHを設定していた場合、想定外の動作をする可能性がある。ruby インタプリタの場合は -x オプションを利用した以下のようなシェルスクリプトに見せかけるトリックを使用したほうが良い。

#!/bin/sh
# -*- ruby -*-
exec ruby -x "$0" "$@"
#!ruby
puts 'Hello world!'

 LinuxディストリビューションFreeBSDでは、envシバンだと動作しないらしい。

 ただ、それでも多くのOSで動作する。それにRubyだけシェルスクリプトにみせかけるトリックを使用のも面倒だし、そのコード量が多すぎる。よって、普段はenvトリックを用いることにする。

所感

 ここまで苦労してシバンを選別して記述したとして、効果はどれほどあるだろうか。費用対効果まで考えると微妙かもしれない。完璧に動作保証されたシバンを書きたいものだ。環境依存はとてもモヤモヤして気持ちが悪い。

対象環境

$ uname -a
Linux raspberrypi 5.10.52-v7l+ #1441 SMP Tue Aug 3 18:11:56 BST 2021 armv7l GNU/Linux