最も移植性の高いシェルは何であり、従うべき関連するベストプラクティスは何ですか? [閉鎖]

最も移植性の高いシェルは何であり、従うべき関連するベストプラクティスは何ですか? [閉鎖]

私は数ヶ月間シェルスクリプトを行ってきましたが、私が書いたコードがbash一部のコンピュータでは動作しないことがわかりました。これはとても残念です。

勉強しなければならないことに気づきました。最大代わりにポータブルシェルスクリプトです。もちろん最初は少し大変でしょうが、結局は報酬を受けると確信しています。私は私のシェルスクリプトをLinuxスイートとBSDスイートを含むほぼどこでも実行したいと思います。 (ただし、Windowsで動作しているかどうかは関係ありません。)

質問

  1. 最も携帯性の良いケースは何ですか?編集:この質問を無視してください

  2. 最も携帯性の高いシェルを使用する際の重大な欠点は何ですか?編集:この質問を無視してください

  3. 移植性の高いコードを書くには、何に注意する必要がありますか?たとえば、どのcore-utilsとどのバージョンを使用して避けるべきですか?

答え1

名前参照()、連想配列()、またはmacOSのデフォルト値を使用しようとするなど、他のシステムのシェルバージョンに新機能を使用しない限り、シェルがインストールされているすべてのコンピュータでスクリプトを実行する必要がありますbash。形式(または他の形式)(これは古いものです。この場合は、Homebrewを使用して最新バージョンをインストールするだけです)。他のシステムで利用できない外部ツール、または実装されていない、または別の方法で実装できるツール機能を使用しても、スクリプトは失敗する可能性があります。bashbashdeclare -ndeclare -A%(...)Tprintfbashbash

POSIXシステムで最も移植性の高いシェル言語はshシェルです。ここで説明します。https://pubs.opengroup.org/onlinepubs/9699919799/idx/shell.html

拡張機能付きのシェルbash(およびその他)が実装されましたsh。次のようなfishいくつかのシェルzshshzshsh--emulate shdash するより純粋にPOSIX標準に従いますsh(しかしまだいくつかの拡張が含まれています)。

一般的に言えば、以下に関連するシェルの側面は通事論そして組み込み機能スクリプトが常に同じシェル(およびある程度シェルバージョン)によって実行される限り、そのシェルがシェルであっても「移植可能」でなければなりませんfish。これはPython、Perl、Rubyスクリプトと同じタイプの「移植性」を持ちます。ただし、通常は実行可能または「互換モード」の一部の形式で実行される利用sh可能なシェル(通常はインストール)が必要です。/bin/shbashdashksh

POSIXシステムで最も移植性の高いユーティリティはPOSIXユーティリティです。これの説明は次のとおりです。https://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html

GNU UtilitiesのユーティリティであるGNU Utilitiesは、coreutilsPOSIXユーティリティを実装します(schilyユーザーとして)コメントとして指摘する、POSIX-という意味ではありません。合法的に) その後、主に便宜のために機能を拡張します。他のUnixシステムの対応するユーティリティも同様です。また、LinuxのGNUパッケージにはcoreutilsPOSIXで指定したすべてのユーティリティは含まれておらず、などfindsedユーティリティawkはPOSIXユーティリティであり、別々にパッケージされています。

POSIXユーティリティを引き続き使用し、POSIXの動作(オプションなどの点で)を使用する限り、POSIX構文を使用するスクリプトのshほとんどのUnixシステムでは「ほとんど移植可能」になります。ただし、POSIX ユーティリティではないユーティリティもあり、POSIX ユーティリティに対する POSIX 以外の拡張もまだ存在します。かなり一般的に実装されているので、移植可能です。 POSIX以外の一般的なユーティリティの例には、およびpkilltarありますgzip。一般的なPOSIXユーティリティの非POSIX拡張の例は、一般的に理解されている-iname述語findと事実です。sed拡大する正規表現の使用-E

どの拡張がどのツールの実装、どのUnicesで、どのように使用されるかを直接テストし(たとえば、仮想マシンで)、このサイトの質問と回答を読んで学ぶことができます。例えば、sed -i(所定の位置で編集)を使用して移植性を達成するには?

また、POSIX標準が「指定されていない」動作を維持する場合もあります。これは、POSIXオプションを使用する同じユーティリティが2つの異なるUnixシステムで異なる動作をする可能性があることを意味します。例はここにあります。権限が大丈夫ですが、シンボリックリンクを新しいターゲットに更新するときに権限が拒否されるのはなぜですか?

これダメージ純粋なPOSIXシェルコードを書こうとするときの最大の欠点は、本当に便利な機能を見逃すことです。私はかつてfindGNUの述語テストに対してPOSIX同等のテストを書こうとしましたが、-readable簡単ではなく、名前の代わりにおよびをps使用してプロセスを表現したいのが、このサイトであまりにも多くの質問のトピックでした。同様に、「POSIXを維持する」にはPOSIXを離れる必要があります。greppkill本当に便利なもの同様に、perlほとんどの管理タスク(ユーザーの追加、バックアップ管理、システム間のファイル転送など)を移植可能な方法で実行することはできません。

一般的に言えば、私は一つを好む忙しい他のシステムをサポートするために私のコードを変更する必要があるかもしれないことを理解しながら、タスクを完了する方法(他のシステムで使用されている場合)純粋主義者方法。だからといって、移植性の問題ができるだけ少ないスクリプトを書くのを防ぐことはできません(どこにでも移植不可能なセマンティクスを使用しません)。しかし、これは私の個人的な意見です。

答え2

ポイントはPOSIXこれらを標準化するために

  1. bashは良いですが、POSIXサブセットを使用します。
  2. 効率が少し落ちるでしょう。
  3. POSIX仕様の残りの部分を読んで、ここと次のような他の場所で時間を過ごしてください。ニュースグループ

答え3

GNU / Linuxシステムで移植可能なスクリプトを作成する場合は、最良のオプションはシェルを使用することですdash。これは、標準以上のアドオンをほとんど提供しない非常にポータブルなシェルです。これは/bin/shDebianとUbuntuシステムの標準です。 Red HatとCentOSはbashをオペレーティングシステムとして使用するため、/bin/sh移植性テストには適していません。

答え4

あなたの質問が間違っているようです。

正しい質問は次のとおりです。「移植可能なスクリプトを取得するにはどうすればよいですか?」

主な移植性の問題は、機能強化を実装するプログラムとそれを使用するユーザーの間にあります。これは、他のUNIXプラットフォームで欠落している可能性が高いためです。

以下は、移植性の問題の一般的な原因の一覧です。

  • GNUスタイルの長いオプションで宣伝されたGNUプログラムは--long100%移植できません。移植可能なスクリプトでは絶対に使用しないでください。

  • バッシュの実装KSHスタイル拡張機能(例:)[[ -z $HOME ]]これはPOSIXにはない機能で、ksh88、ksh93、bash、mkshのみを実装します。

  • bash(Mac OSおよびSolarisで使用されるコンパイルオプションでコンパイルされていない場合)は、echoUNIXの動作と競合する非POSIX組み込みコマンドを実装します。注意してください。また、以下の事項も参考にしてください。

  • printf一部の実装は文字列引数の nul バイトを正しく処理しないため、他の printf 実装は異なる機能セットを持つため、Printf も最終的なソリューションではありません。

  • 1、2、3、6、9、14、15以外の信号番号は移植できません。関連するシグナルは、UNIXのバージョンによって名前/番号マッピングが異なります。

  • POSIXシェル数学などは、echo $(( a + b ))シェルごとにサポートされる機能セットが異なるため、移植性の問題を引き起こす可能性があります。 POSIXには限られた機能セットのみが必要です。

  • POSIXシェルは通常いいえ/bin/shPOSIXは、パス名が存在しない限りパス名を処理しないためですdev/tty。 POSIXシェルを起動するには、呼び出してgetconf PATH結果をPATHシェルとして使用し、入力するとshPOSIXシェルが作成されます。

  • /bin一般的に期待される他のすべてのユーティリティーは、ユーティリティーの/usr/binPOSIXバリアントではありません。次に電話する必要があります。

    PATH=`getconf PATH`
    export PATH
    sh
    

    ユーティリティのPOSIXバリアントを呼び出すPOSIXシェルを取得します。

多くの人がテスト用に推奨していますが、マルチバイト文字サポートを実装していないため、POSIXを認識できないためdash問題になります。dash

私が推奨するのは、デフォルトでオンになっている最小限のPOSIX機能を実装するためにpboshこれを使用することです。boshpbosh

関連情報