web-dev-qa-db-ja.com

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

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

[〜#〜] update [〜#〜]

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

Linux/usr/bin/passwd -u $ USERNAME

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

「uname」の結果に基づいてShebangを定義できますか?

4
SpruceTips

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

2
Mix999

最も簡単な方法は、両方のシステムで同じシェルを使用することです。 1つのシェルがプリインストールされているからといって(スクリプトの「デフォルトシェル」などはありません。シェルはShebangの行にあるとおりです)、他のシェルをインストールできないという意味ではありません。 aixにbashをインストールする(たとえば、 toolbox から)か、Linuxの場合はksh93をインストールできます(ディストリビューションのパッケージマネージャーを使用:kshパッケージをインストールします)。

Kshを選択する場合、AIXの_/usr/bin/ksh_はksh88であることに注意してください。 Linux用のksh88のバージョンはなく、AIXで_/usr/bin/ksh93_として使用できるksh93のみがあります。

同じシェルを両方のシステムの同じ場所にインストールすると(シンボリックリンクで問題ありません)、Shebangラインで同じパスを使用できるため、より簡単です。同じ場所を使用するのが難しい場合は、両方のシステムでbashPATHにあることを確認する限り、_#!/usr/bin/env bash_のようなものを使用できます。これは、rootアクセス権がないために、ホームディレクトリにbashまたはkshをインストールする必要がある場合に役立つことがあります。

両方のマシンに同じシェルを実際にインストールできない場合(おそらく、人々の生活を複雑にするだけで、定着しすぎて覆すことができない愚かなコンプライアンスルールがあるため)、いくつかの可能性があります。

  • _#!/bin/sh_をシバンラインとして使用し、システムが提供するものの交差点でプログラムします。最新のUNIXシステムはすべて、 POSIX Shell as _/bin/sh_を提供します。 AIXでは、_/bin/sh_はksh88です。 Red Hatでは、_/bin/sh_はbashです(shとして呼び出された場合の動作は少し異なります)。他のいくつかのオペレーティングシステム(たとえば、多くのLinuxディストリビューション)では、_/bin/sh_は小さいシェルであり、POSIX機能をはるかに超えるものではない可能性があることに注意してください。
  • より良いシェルを探して実行する定型コードでスクリプトを開始します。

    _#!/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拡張パターンを有効にするには、_shopt -s extglob_を実行します。

同様の要件がありました。連想配列をサポートするには、AIX5.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
1
Patrick

Gillesの答えは(いつものように)素晴らしいですが、あなたがそれを選択したり、賛成票を投じたりしなかったので、おそらくあなたはそれが複雑すぎると感じるでしょう。したがって、ここでは、役立つ場合と役に立たない場合があり、2つの別々のスクリプトを維持することを回避するのに役立つ可能性のあるいくつかの(単純な)ポイントを示します。

1)AIXマシンには、インタラクティブに使用するためのデフォルトのシェルではない場合でも、bashがインストールされている可能性があります。 (私が使用しているAIXマシンにはbashがインストールされていますが、システム管理者が追加した方法でそれが行われたかどうかはわかりません。すべてのシステム管理者がksh junkies。)そして、RHELマシンにkshがインストールされていることは間違いありません。両方のマシンで同じシェルを使用できる場合は、多くの手間を省くことができるため、これを確認してください。

2)シェルが設置される場所がわからない場合は、そのパスを直接シバンラインに配置しないでください。代わりに、次のように、envへのパスとシェル実行可能ファイル名を後で入力します。

#!/usr/bin/env bash

このshouldは両方のマシンで機能するはずですが、確実にテストする必要があります。 (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"
0
iconoclast

両方のシステムで機能するコマンドを備えた1つのバージョンを実際に使用できるかどうかを確認するためにいくつかの作業を行います。

Dotfilesリポジトリに保存している.bashrcファイルでこの問題が発生しました。 OSXとUbuntuの両方で動作させたいのですが、そのために変更する必要のあるコマンドがいくつかありました。この場合、ほとんどの場合、特定のコマンドに対してどのスイッチが機能したか、またはテストコマンドがどのように記述されたかでした。私はそれぞれの問題に取り組み、両方のOSで機能する形式で試しているコマンドを実行する方法を見つけました。

「OSに応じて2つの異なるファイル」と「2つの異なるセクション」のアプローチを試しましたが、それらを維持するのが面倒でした。

0
Michael Durrant