エラー
このタスク内の612行目にある
sh: 1: Syntax error: Bad fd number
の部分です。
このエラーはRakefileの中で
system "git push #{quiet} -f origin #{deploy_branch} >& /dev/null"
としてる部分から来ています。
エラーが出るのは>&
の部分での出力のリダイレクトの部分です。
もともと>&
という書き方はcsh
やtcsh
で標準出力とエラー出力を
同時に同じものにリダイレクトする時の書き方で、
これが使えない状況なのに使ってるのが問題。
原因
Travisの通常のscript
等の行に書くコマンドは
Bashで実行され(Bash 4.2.24)、
Bashでもこの方法は使えるはずで
1、
実際Travisのスクリプトの指定でも使ってたりもしてましたが問題ありませんでした。
問題はRakefileの中でSysem
でコールしてる部分なので、
これを調べてみると、TravisのLinux環境では/bin/sh
がdash
に
リンクされてる事が分かりました。
Rubyのスクリプトの中とかからSystem
みたいな形でコマンドを呼ばれると
/bin/sh
が使われるためdash
になり、
dash
では>&
でリダイレクトすることは出来ないのでエラーが出ます。
解決法
解決するためには、この部分を
1 2 |
|
みたくdash
でも使える形にしてあげるだけ。
TravisのLinux環境は/bin/sh
がdash
になってるため、
その辺り気をつけてスクリプトなどを準備する必要がある、ということです。
OS X環境
Travisでは現状では
language: objective-c
と、.travis.ymlでlanguageをobjective-cにした場合だけ OS Xの環境でジョブを走らせます。
この環境を見てみると、Bashは3.2.51がデフォルトで、 /bin/shは同じくBash 3.2.51になっています。
なので、こちらで走らせるときは上の様なスクリプトも問題なく動きます。
まとめ
OS Xの場合には/bin/sh
がbash
になってますが、
dash
であるシステムも存在するので、
色々書くときに、Rubyとかプログラムの中からシステムコールする様な
場合には/bin/sh
を使うようになり、さらにそれがdash
の可能性も考慮して
使うコマンドはPOSIX準拠なものにすべきということです。
勿論Shebangに/bin/sh
を指定してる様なスクリプトでも同様。
dash
で使えないものとしては他にも&>
を使ったリダイレクト
(bash
などでは>&
と一緒)もダメです。
[[~]]
と二重括弧によるテストや==
による比較、
((~))
による計算方法も使えませんがこの辺は短いシステムコール位では余り使わないので
あまり気にするところではないかもしれません。
bash
とdash
の違いについて詳しくは下のスライドが良くまとまっています。
上のスライドは下の本の著者が書いたみたいです。
-
Redirecting Standard Output and Standard Error
This construct allows both the standard output (file descriptor 1) and
the standard error output (file descriptor 2) to be redirected to the
file whose name is the expansion of word.There are two formats for redirecting standard output and standard
error:&>word
and
>&word
Of the two forms, the first is preferred. This is semantically equiva-
lent to>word 2>&1
When using the second form, word may not expand to a number or -. If
it does, other redirection operators apply (see Duplicating File
Descriptors below) for compatibility reasons.