複数のシェルでスクリプトを実行していますか?

複数のシェルでスクリプトを実行していますか?

2つのサーバーがあります。 1つはデフォルトのシェルkshを持つAIX、もう1つはデフォルトのシェルbashを持つRHELです。

同様のコマンドを実行しましたが、AIXまたはLinux用にスクリプトをインストールしました。スクリプトはbashサーバー上で実行されません。 bashとkshでスクリプトを実行する方法はありますか、それとも2つの異なるスクリプトを生成するための最良のオプションはありますか?

#!/usr/bin/ksh
export OS=`uname -s`
echo "OS is "$OS"."
case $OS in
        "AIX")
                #run AIX commands;;
        "Linux")
                #run Linux commands;;
        "*")
                echo "Exiting. The OS type is not found.";;
esac
echo "Done."
exit 0

修正する

私が実行する必要があるコマンドは、各サーバーのユーザーアカウント用です。アカウントのロック解除の例。 AIX /usr/bin/chuser account_locked=false $USERNAME

Linux /usr/bin/passwd -u $ユーザー名

さらなる調査により、AIX のシェル位置は /usr/bin/sh にあり、Redhat のシェル位置は /bin/sh にあることがわかりました。

"uname"の結果に基づいてshebangを定義できますか?

答え1

最も簡単な方法は、両方のシステムで同じシェルを使用することです。シェルがプリインストールされて提供されるからといって(スクリプトに対する「デフォルトシェル」のようなものはなく、シェルは shebang 行で言う通りである)他のシェルをインストールできないという意味ではありません。 AIXにbashをインストールできます(ツールボックス、例えば)またはLinuxの場合、ksh93(配布版のパッケージマネージャを使用する:パッケージのインストールksh)。

kshを選択した場合、/usr/bin/kshAIXではksh88です。 Linuxにはksh88バージョンがなく、/usr/bin/ksh93AIXで使用可能なksh93バージョンのみがあります。

両方のシステムの同じ場所に同じシェルをインストールすると(シンボリックリンクが可能です)、shebang行で同じパスを使用できる場合は簡単になります。同じ場所を持つのが難しい場合は、両方のシステムにいることを#!/usr/bin/env bash確認する限り、同様のものを使用できます。これはrootアクセス権がないため、ホームディレクトリにbashまたはkshをインストールする必要がある場合に便利です。bashPATH

実際には、両方のシステムに同じシェルをインストールできない場合(おそらく人々の生活を複雑にしますが、反転するには根強い愚かなコンプライアンスルールがあるため)、いくつかの可能性があります。

  • #!/bin/shシステムが提供するクロスワイヤーおよびプログラムとして使用してください。すべての最新のUNIXシステムは、以下を提供します。POSIXシェルのように/bin/sh。 AIXでは/bin/shksh88です。 Red Hatでは/bin/shbashです(呼び出すと少し違うように動作しますsh)。他のオペレーティングシステム(たとえば、多くのLinuxディストリビューション)は、/bin/shPOSIXよりも多くの機能を持っていない可能性がある小さなシェルです。
  • より良いシェルを見つけて、実行するいくつかの定型句コードでスクリプトを起動します。

    #!/bin/sh
    if [ -n "$BASH" ]; then
      … bash compatibility code …
    elif type whence >/dev/null 2>/dev/null; then
      … ksh compatibility code …
    elif type ksh93 >/dev/null 2>/dev/null; then
      exec ksh93 "$0" "$@"
    elif type ksh >/dev/null 2>/dev/null; then
      exec ksh "$0" "$@"
    elif type mksh >/dev/null 2>/dev/null; then
      exec mksh "$0" "$@"
    elif type bash >/dev/null 2>/dev/null; then
      exec bash "$0" "$@"
    else
      echo 1>&2 "Cannot find ksh or bash, aborting"
      exit 125
    fi
    

どちらの場合も、ksh88とbashの交差点はPOSIX以上の便利な機能を提供しますが、いくつかの互換性コードが必要な場合があります。特に:

  • ksh88での配列割り当ての使用をset -A参照してください。各種ksh環境の代入変数
  • ローカル変数はとして宣言されますtypeset
  • Ksh88いいえ${VAR/PATTERN/REPLACEMENT}$'…'またはFIGNORE。はい[[ … ]]
  • @(…)Bashでkshおよびその他のksh拡張モードを有効にするには、を実行しますshopt -s extglob

答え2

2つの異なるバージョンのスクリプトを使用する方が簡単かもしれません。短すぎるため、jw013が提案したように、2つの形式の違いを処理するために追加のコードを追加することは価値がありません。一方、大きなスクリプトがある場合は、1つのスクリプトを使用し、実行場所に応じて別のコマンドを実行する方が簡単です。

答え3

同様の要件があります。 AIX 5.3では、ksh93を使用して連想配列をサポートする必要があります。そのため、ksh93を使用して2番目のインスタンスを起動するスクリプトを設定しました。また、繰り返し再生成されるのを防ぐために、保護機能も追加しました。

#!/bin/ksh

scr=$0
safe=$1
echo "Check OS to determine if ksh93 is needed..."
if ( `typeset -A testvar > /dev/null 2>&1` ); then
  echo "Associative array functions supported."
else
  echo "Associative array functions NOT supported. Starting second instance with ksh93..."
  if [ "$safe" -eq 1 ]; then
    echo "SECOND INSTANCE ALREADY STARTED!"
    exit 1
  else
    echo "BEGIN SECOND INSTANCE USING KSH93"
    /bin/ksh93 $scr 1
    exit 0
  fi
fi

答え4

Gilesの答えは(IMHO)素晴らしいです(いつものように)。しかし、選択しなかったし、投票もしなかったので、あまりにも複雑だと思ったかもしれません。したがって、役に立つかもしれないし、そうでないかもしれないいくつかの(簡単な)ことがあります。することができます。

1)bash対話式使用のためのデフォルト・シェルでなくても、AIX システムにインストールされている可能性があります。 (私が使用しているAIXマシンにはこの機能がインストールされていますが、bashシステム管理者が追加したかどうかはわかりません。私たちのシステム管理者はすべて薬物中毒者なのでそのようにインストールしたようkshです。)私は喜んでそうします。 RHELシステムに賭けましたksh。すでにインストールされています。両方のシステムで同じシェルを使用できる場合は節約できるので、これを確認してください。たくさん問題。

2)シェルがどこにインストールされるかわからない場合は、シェルパスをshebang行に直接入力しないでください。代わりに、以下のようにパスenvとシェルの実行可能ファイル名を入力してください。

#!/usr/bin/env bash

これしなければならない両方のコンピュータで動作しますが、確認するにはテストする必要があります。 (envまたはほとんどの事物の立場よりも、その立場がより標準的だと主張します。)bash

両方のシステムで同じシェルを使用すると、問題が解決する可能性があります。しかし、そうでなければ...

3)ソースコードのプラットフォーム固有のコードを基本スクリプト内の関数に分割できます。つまり、スクリプトに場所AIX で実行しているのか、RHEL で実行しているのかによって状況が異なるように動作するため、プラットフォームを再確認する必要はありません。一度だけ実行すると、適切な機能が得られます。

case $OS in
    "AIX")
            source aix_functions;;
    "Linux")
            source redhat_functions;;
    "*")
            echo "Exiting. The OS type is not found.";;
esac

caseこれで、プラットフォームを区別するために追加のステートメントを使用せずに、スクリプト全体で取得できるすべての機能を使用できます。

do_something_platform_specific "$SOME_ARGUMENT" "$SOME_OTHER_ARGUMENT"

関連情報