Mac/Linux間でシェルスクリプトの絶対パスやdateの違いを吸収する

こんにちは、hachi8833です。BPS社内Slackの#macチャンネルのやりとりからです。

160830_1932_niXaHL

パスとdateをPerlで取得

perlのrel2abs()で絶対パスを取得し、strftime()で日時を数字のみで取得しています。

ENV_PATH=$(perl -MFile::Spec -e "print File::Spec->rel2abs( \"$0\" )")
EXEC_DATETIME=$(perl -MPOSIX -e "print strftime(\"%Y%m%d%H%M%S\", localtime)")

も少し短く

続いて「こっちならもうちょっと短いよー」との意見も出ました。

160906_1505_kzMiG9

perl -MCwd -le 'print Cwd::abs_path(".")'

perlならMacとLinuxの両方でほぼ確実に利用できます。凝ったコードにするとperlのバージョンの互換性の問題が生じるかもしれないので、このようなワンライナーにとどめておくのがよいでしょう。

それにしても、Dockerコンテナ化されたプロジェクトならこういうことを気にせずに安心してシェルスクリプトを書けるのにと思います。

Rubyで書いてみた

今回の目的では使いませんが、Rubyで書くと次のような感じになりますね。

ENV_PATH=$(ruby -e “print Dir::getwd”)
EXEC_DATETIME=$(ruby -e “print Time.now.strftime(‘%Y%m%d%H%M%S’)”)</p>

補足:プラットフォーム互換について

ネタ元のmorimorihogeです。
小さなシェルスクリプトはWeb系エンジニアは嗜みとして利用されていると思います。Rails系システムであれば、定期実行にはWheneverを使ってrake taskを呼び出したり非同期実行であればDelayed::JobResqueSidekiqを使えば、ディストリビューションに依存しないバッチ処理が作成できて問題も少ないので、基本的にはそちらに倒すと楽ができます。

ただ、Webアプリを開発するチームとインフラ管理をしているチームが責任範囲や組織的に分かれている場合には、お互いの共通言語ということでシェルスクリプトを使うのがトラブルが少ないでしょう。
特にインフラ周りを担当されているエンジニアがある程度のルールを持っている場合、シェルスクリプトで書いておくことでインフラエンジニア側で後から多少修正するといったことも簡単にできるようになります。

ただ、Webアプリのシステム中にシェルスクリプトを混ぜ込む時には本記事の様にある程度プラットフォーム互換を意識して書いておかないと、開発者のMacでは動くけどstagingに持っていったときに動かないといった現象が発生してしまいます。
もちろん「このバッチはLinux環境でしか動かさないよ!」というルールで開発・運用をしても良いのですが、その場合は開発者の手元でテストされなくなって問題がスルーされてしまう可能性が高まります。

Dockerを使って・・・という解決策も確かにありますが、それはそれでDockerの使い方をサポートしたりしないといけなくて辛みもあります(弊社社内ではまだDockerを完全に標準開発環境として整備しきれていない)。
他社のエンジニアと連携して動くこともあるので、後で説明が面倒なことになるよりはおとなしくマルチプラットフォーム動作するように書いてしまった方が結果として面倒がないかな、とも思いました。

関連記事

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833 コボラー、ITコンサル、ローカライズ業界を経てなぜかWeb開発者志願。 これまでにRuby on Rails チュートリアルの大半、Railsガイドのほぼすべてを翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

Rubyスタイルガイドを読む

BigBinary記事より

ActiveSupport探訪シリーズ