2017-04-24 9 views
0

でハング:ラッパーbashスクリプトはkshのスクリプトを呼び出しますが、私はbashスクリプト</p> <p>foo.sh持っている機能

#!/bin/bash 
echo "start" 
. /path/to/bar/bar.ksh 
echo "after bar" 

getoravariables $1 

はbar.ksh(目的はOracleだけ変数を設定することです):

#!/bin/ksh 
echo "b4 getora" 
getoravariables() { 
echo "1" 
if [ $# -ne 1 ] 
then 
echo "2" 
     echo "Usage: getoravariables sid" 
     exit 1 
fi 

grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g" | read SID ORAHOME ASK 


if [ $? -ne 0 ] 
then 
     print "Error: Please enter a vaild SID and check the ${orafile} file for correct input" 
     return 1 
fi 

ps -ef|grep pmon|grep ${SID} >> /dev/null 

if [ $? -ne 0 ] 
then 
     print "Error: SID ${SID} does not seem to be started. " 
     return 2 
fi 

export ORACLE_SID=${SID} 
export ORACLE_HOME="${ORAHOME}" 
export ORAENV_ASK=NO 

. $ORACLE_HOME/bin/oraenv > /dev/null 

} 
echo "after getora" 

foo.shを実行した後、私は得る:

>./foo.sh validsid 
start 
b4 getora 
after getora 

したがって、 "b4 getora"と "getoraの後ろ"のechoコマンドが機能するので、単にkshスクリプトを呼び出すだけで問題はないことが分かります。しかし、私が期待するエコー "1"またはエコー "2"が得られないので、この関数を実行する際に問題があります。

さらに、foo.shをkshスクリプトとして実行すると、すべて正常に動作します。

したがって、私は、2つの言語間で文法に何らかの違いがあると推測できます。誰も助けることができますか?

UPDATE: 私は(私が私の質問に含まことがちょうどサブセットです)、私の完全なkshのスクリプトの先頭にset -xを追加しました。

++ echo 

++ grep -v '#' 
++ read VAR VALUE 
(hanging here) 

スクリプトのこの部分のために、これらのコードは次のとおりです:

echo $GLOBPARFIL 
grep -v "#" ${GLOBPARFIL}|while read VAR VALUE 
do 
     export ${VAR}=${VALUE} 
done 

Soは$GLOBPARFILは設定されません。私は、スクリプトが機能は、私が投稿私のスクリプトで後の時点でハングことがわかりました正しく。また、それは引き込まれてgetoravariables()から設定される変数になります。報復をデバッグからの出力はこのことを示しています。

++ read VAR VALUE 
++ export GLOBPARFIL=/home/local/par/global.par 
++ GLOBPARFIL=/home/local/par/global.par 

このラインアップ@jlliagre答えているが、変数が正しく設定取得されていないことを宣言下回ります。しかし、私は同じ望ましくない結果だけで回避策を試しました。

UPDATE 2:私は、本当の原因を見つけ、回避策を作成することができた提供された情報とロジックに続い

問題:

grep -v "#" ${file_location}| tr "^" " " | while read VAR VALUE 

SOLUTION:

while read VAR VALUE 

do 

     export ${VAR}=${VALUE} 
done <<% 
$(grep -v "#" ${file_location}| tr "^" " ") 
% 

私は結婚するkを完了します。しかし、なぜこの回避策が問題を解決するのかという理由でもっと情報を得ることができたら、私はそれを高く評価します。

答えて

3

ファイルをソーシングすると、シバンは無視されるので、kshを参照しているため、bashはそれを処理できません。

問題は、その行である:

kshの下
grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g" | read SID ORAHOME ASK 

bashの下に、それはサブシェルで実行されている間、パイプラインの最後のコンポーネントは、メインシェルによって実行されます。変数SID,ORAHOMEおよびASKは、bashに設定された直後に失われます。ここで

は、回避策です:

read SID ORAHOME ASK <<% 
$(grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g") 
% 

編集:あなたが使用する可能性のある第二の問題については、

while read VAR VALUE 
do 
     export ${VAR}=${VALUE} 
done <<% 
$(grep -v # "${GLOBPARFIL}") 
% 

GLOBPARFILが設定されている場合は、変数が正しく設定されるだろうし、エクスポートされ、GLOBPARFILが設定されていない場合、これはおそらく問題であり、少なくともスクリプトをハングしません。

説明:

シェル・コマンドパイプラインを実行すると、例えばcommand1 | command2 | command3の場合、bashインタプリタはすべてのコマンドをサブシェルで実行しています。つまり、パイプラインコマンドの1つで行われた変数の設定が失われます。あなたのスクリプトには、いくつかのイディオムがあります(command 1 | read variable1 variable2)。現在のシェルでread命令を実行しますが、bashでは実行しないkshで動作します。

移植可能な回避策は、行の先頭にある変数を読み取ってコマンドの順序を逆にし、here documentを使用して読み取り標準入力を設定します。ここの文書は任意のカスタム文字列で区切られ、一般的なものは%です。ここの文書には通常、標準入力自体がプレーンテキストとして含まれています。ここでは、この入力をパイプラインのset命令の前にあるコマンドの結果にするため、command substitution$(command))が使用されます。これはcommandの出力をhereドキュメントに入れています。

あなたはまたprocess substitutionを使用している場合があります:

read SID ORAHOME ASK < <(grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g") 

...

while read VAR VALUE 
do 
     export ${VAR}=${VALUE} 
done < <(grep -v "#" "${GLOBPARFIL}") 
+0

ありがとうございます、私の例のbar.kshスクリプトは、実際は私の大きなスクリプトのサブセットです。あなたの答えは私の本当のバーなら質問しました。kshはそれを最後までしていました。私はそれの最後にエコーを入れ、それは戻っていませんでした。問題は他の場所になければならない、私はソースを見つけるためにもっと仕事をしなければならない。 –

+0

@ exit_1シェルスクリプトをデバッグするには、最初に 'set -x'を入力します。次に、実行するすべての行が表示されます。 – Barmar

+0

はい、または単に 'bash -x foo.sh'を実行してください。 – jlliagre

0

を最も可能性の高いシナリオは、関数名 'getoravariables' はdoesnの第2の機能を(定義するために使用されたということですここにリストされていないスクリプトの中には何も見えません)。 すべてのファイルで「getoravariables」のgrepを試してみてください。

0

スクリプトのbash実行を「強制」するようなスクリプトがあります。

#!/bin/sh 
# 

if [ "$(ps -p "$$" -o comm=)" != "bash" ]; then 
    exec /usr/local/bin/bash "$0" "[email protected]@" 
    exit 255 
fi 
echo blah... 

kshの実行を強制するためにこのようなことができると仮定します。 psオプションはPOSIXなので、portable-ishでなければなりません。

P.S.これを行うより良い方法がある場合は、投稿してください。私は誇りに思っていません。

関連する問題