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/ksh
AIXではksh88です。 Linuxにはksh88バージョンがなく、/usr/bin/ksh93
AIXで使用可能なksh93バージョンのみがあります。
両方のシステムの同じ場所に同じシェルをインストールすると(シンボリックリンクが可能です)、shebang行で同じパスを使用できる場合は簡単になります。同じ場所を持つのが難しい場合は、両方のシステムにいることを#!/usr/bin/env bash
確認する限り、同様のものを使用できます。これはrootアクセス権がないため、ホームディレクトリにbashまたはkshをインストールする必要がある場合に便利です。bash
PATH
実際には、両方のシステムに同じシェルをインストールできない場合(おそらく人々の生活を複雑にしますが、反転するには根強い愚かなコンプライアンスルールがあるため)、いくつかの可能性があります。
#!/bin/sh
システムが提供するクロスワイヤーおよびプログラムとして使用してください。すべての最新のUNIXシステムは、以下を提供します。POSIXシェルのように/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およびその他の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"