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を定義できますか?
スクリプトの2つの別々のバージョンを用意する方がおそらく簡単でしょう。短いので、jw013が提案したように、2つの形式の違いを処理するためにコードを追加する価値はないかもしれません。一方、より大きなスクリプトがある場合は、スクリプトを作成して、実行元に応じてスクリプトに異なるコマンドを実行させる方がおそらく簡単です。
最も簡単な方法は、両方のシステムで同じシェルを使用することです。 1つのシェルがプリインストールされているからといって(スクリプトの「デフォルトシェル」などはありません。シェルはShebangの行にあるとおりです)、他のシェルをインストールできないという意味ではありません。 aixにbashをインストールする(たとえば、 toolbox から)か、Linuxの場合はksh93をインストールできます(ディストリビューションのパッケージマネージャーを使用:ksh
パッケージをインストールします)。
Kshを選択する場合、AIXの_/usr/bin/ksh
_はksh88であることに注意してください。 Linux用のksh88のバージョンはなく、AIXで_/usr/bin/ksh93
_として使用できるksh93のみがあります。
同じシェルを両方のシステムの同じ場所にインストールすると(シンボリックリンクで問題ありません)、Shebangラインで同じパスを使用できるため、より簡単です。同じ場所を使用するのが難しい場合は、両方のシステムでbash
がPATH
にあることを確認する限り、_#!/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を超えるいくつかの便利な機能を提供しますが、少しの互換性コードが必要になる場合があります。特に:
set -A
_を使用します。 異なるksh環境での割り当て変数 を参照してください。typeset
によって宣言されます。${VAR/PATTERN/REPLACEMENT}
_、_$'…'
_、またはFIGNORE
がありません。 _[[ … ]]
_があります。@(…)
およびその他の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
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"
両方のシステムで機能するコマンドを備えた1つのバージョンを実際に使用できるかどうかを確認するためにいくつかの作業を行います。
Dotfilesリポジトリに保存している.bashrc
ファイルでこの問題が発生しました。 OSXとUbuntuの両方で動作させたいのですが、そのために変更する必要のあるコマンドがいくつかありました。この場合、ほとんどの場合、特定のコマンドに対してどのスイッチが機能したか、またはテストコマンドがどのように記述されたかでした。私はそれぞれの問題に取り組み、両方のOSで機能する形式で試しているコマンドを実行する方法を見つけました。
「OSに応じて2つの異なるファイル」と「2つの異なるセクション」のアプローチを試しましたが、それらを維持するのが面倒でした。