rcmdnk's blog

Geometry Dash Lite

Travis CIでジョブを走らせてたら Syntax error: Bad fd number というエラーが出てたのでそれを治した話。

問題は/bin/shと意識してなかったことでした。

Sponsored Links

エラー

https://travis-ci.org/rcmdnk/octogray/builds/38268981

このタスク内の612行目にある

sh: 1: Syntax error: Bad fd number

の部分です。

このエラーはRakefileの中で

system "git push #{quiet} -f origin #{deploy_branch} >& /dev/null"

としてる部分から来ています。

エラーが出るのは>&の部分での出力のリダイレクトの部分です。

もともと>&という書き方はcshtcshで標準出力とエラー出力を 同時に同じものにリダイレクトする時の書き方で、 これが使えない状況なのに使ってるのが問題。

原因

Travisの通常のscript等の行に書くコマンドは Bashで実行され(Bash 4.2.24)、 Bashでもこの方法は使えるはずで 1、 実際Travisのスクリプトの指定でも使ってたりもしてましたが問題ありませんでした。

問題はRakefileの中でSysemでコールしてる部分なので、 これを調べてみると、TravisのLinux環境では/bin/shdashに リンクされてる事が分かりました。

https://travis-ci.org/rcmdnk/travis-test/builds/39787800

Rubyのスクリプトの中とかからSystemみたいな形でコマンドを呼ばれると /bin/shが使われるためdashになり、 dashでは>&でリダイレクトすることは出来ないのでエラーが出ます。

解決法

解決するためには、この部分を

1
2
- system "git push #{quiet} -f origin #{deploy_branch} >& /dev/null"
+ system "git push #{quiet} -f origin #{deploy_branch} > /dev/null 2>&1"

みたくdashでも使える形にしてあげるだけ。

TravisのLinux環境は/bin/shdashになってるため、 その辺り気をつけてスクリプトなどを準備する必要がある、ということです。

OS X環境

Travisでは現状では

language: objective-c

と、.travis.ymllanguageobjective-cにした場合だけ OS Xの環境でジョブを走らせます。

この環境を見てみると、Bashは3.2.51がデフォルトで、 /bin/shは同じくBash 3.2.51になっています。

https://travis-ci.org/rcmdnk/travis-test/builds/39787748

なので、こちらで走らせるときは上の様なスクリプトも問題なく動きます。

まとめ

OS Xの場合には/bin/shbashになってますが、 dashであるシステムも存在するので、 色々書くときに、Rubyとかプログラムの中からシステムコールする様な 場合には/bin/shを使うようになり、さらにそれがdashの可能性も考慮して 使うコマンドはPOSIX準拠なものにすべきということです。

勿論Shebangに/bin/shを指定してる様なスクリプトでも同様。

dashで使えないものとしては他にも&>を使ったリダイレクト (bashなどでは>&と一緒)もダメです。 [[~]]と二重括弧によるテストや==による比較、 ((~))による計算方法も使えませんがこの辺は短いシステムコール位では余り使わないので あまり気にするところではないかもしれません。

bashdashの違いについて詳しくは下のスライドが良くまとまっています。

bash vs. dash - PrincessLeia.com

上のスライドは下の本の著者が書いたみたいです。

Sponsored Links
  1. 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.

    man bash (4.3.30)

Sponsored Links

« Yosemiteの高速化等 Firefoxで'このブラウザではJavaScriptが無効になっているか、サポートされていないようです。'と言われた »