2017-04-24 3 views
0

ich ein Bash-SkriptWrapper Bash-Skript ruft Skript KSH aber hängt an einer Funktion

foo.sh haben:

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

getoravariables $1 

bar.ksh (Ziel ist es, Oracle-Variablen nur eingestellt):

#!/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" 

Nach der Ausführung foo.sh ich:

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

So kann ich sagen, dass es kein Problem gibt, einfach das ksh-Skript aufzurufen, da die echo-Befehle für "b4 getora" und "after getora" funktionieren. Aber es gibt ein Problem mit der Ausführung der Funktion, da ich kein Echo "1" oder Echo "2" bekomme, was ich erwarten würde.

Darüber hinaus, wenn ich foo.sh als ksh-Skript ausführen, funktioniert alles gut.

Daher kann ich davon ausgehen, dass es eine Art Unterschied in der Syntax zwischen den beiden Sprachen gibt, die ich nicht fange. Kann jemand helfen?

UPDATE: Ich habe set -x an der Spitze meines vollen KSH-Skript, (was ich in meiner Frage enthalten ist nur eine Teilmenge). Ich fand, dass das Skript an einem Punkt später in meinem Skript hing, dass die Funktion, die ich geschrieben:

++ echo 

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

Diejenigen Code für diesen Teil des Skripts ist:

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

So $GLOBPARFIL nicht fertig richtig. Es ist auch eine Variable, die von getoravariables() gezogen und gesetzt wird. Die Ausgabe von tat Debuggen zeigt dies:

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

Diese Linien mit @jlliagre Antwort unten, dass erklärt, dass die die Variablen nicht richtig eingestellt zu werden. Ich habe jedoch die Problemumgehung mit nur dem gleichen unerwünschten Ergebnis versucht.

UPDATE 2:

Im Anschluss an die Informationen und Logik ich in der Lage war, die wahre Quelle zu finden und eine Abhilfe zu schaffen:

PROBLEM:

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

LÖSUNG:

while read VAR VALUE 

do 

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

Ich werde mar k als abgeschlossen. Aber wenn ich mehr Informationen darüber erhalten könnte, warum genau diese Problemumgehung das Problem löst, würde ich es sehr begrüßen.

Antwort

3

Das Sourcing einer Datei ignoriert den Shebang, so dass die Tatsache, dass es sich auf ksh bezieht, bash nicht verhindert, um es zu verarbeiten.

Das Problem ist mit der Zeile:

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

Unter ksh, die letzten Komponente einer Rohrleitung wird durch die Hauptschale läuft, während sie unter heftigen Schlag, es von einem Subshell ausgeführt wird. Die Variablen SID,ORAHOME und ASK gehen dann gleich nach dem Setzen unter bash verloren.

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

Edit::

hier eine Abhilfe ist

Für die zweite Ausgabe, können Sie verwenden:

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

Wenn GLOBPARFIL gesetzt ist, würden die Variablen richtig eingestellt und exportiert und wenn GLOBPARFIL ist nicht festgelegt, was wahrscheinlich ein Problem ist, würde das Skript zumindest nicht hängen.

Erläuterung:

Wenn Sie eine Shell-Befehl Pipeline laufen, zum Beispiel command1 | command2 | command3, der bash Interpreter führt jeden Befehl in einer Subshell aus. Das bedeutet, dass alle Variableneinstellungen in einem der Pipeline-Befehle verloren gehen. In Ihrem Skript haben Sie mehrere command 1 | read variable1 variable2 Idiome. Dies funktioniert mit ksh, die die read Anweisung in der aktuellen Shell ausführen, aber nicht mit bash.

Eine portable Problemumgehung besteht darin, die Reihenfolge der Befehle umzukehren, indem Sie die Variable am Anfang der Zeile lesen und here document verwenden, um die Lese-Standardeingabe festzulegen. Ein Here-Dokument wird durch eine beliebige benutzerdefinierte Zeichenfolge begrenzt, und eine allgemeine Zeichenfolge lautet %. Ein Here-Dokument enthält normalerweise die Standardeingabe selbst als Klartext. Hier soll diese Eingabe das Ergebnis der Befehle sein, die der Anweisung set in der Pipeline vorangestellt wurden, so dass command substitution ($(command)) verwendet wird. Dies setzt command Ausgabe in das hier Dokument.

Sie könnten auch process substitution verwendet:

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

Vielen Dank, mein Beispiel bar.ksh Skript ist eigentlich eine Untermenge eines größeren Skripts von mir. Ihre Antwort hat mich gefragt, ob meine echte Bar.Ksh hat es bis zum Ende geschafft. Am Ende gab ich ein Echo und es kam nicht zurück. Das Problem muss woanders liegen, ich muss mehr arbeiten, um die Quelle zu finden. –

+0

@ exit_1 Um Shell-Skripte zu debuggen, setze 'set -x' an den Anfang. Es zeigt dann alle Zeilen an, während sie ausgeführt werden. – Barmar

+0

Ja, oder einfach "bash -x foo.sh" ausführen. – jlliagre

0

Das wahrscheinlichste Szenario ist, dass der Name der Funktion 'getoravariables' verwendet wurde, eine zweite Funktion zu definieren (die doesn tue nichts sichtbar) in einem der Skripte, die hier nicht aufgeführt sind. Versuchen Sie in all Ihren Dateien nach 'getoravariables' zu suchen, vielleicht finden Sie es.

0

Ich habe ein Skript wie folgt, um die Ausführung eines Skripts "forcieren".

Ich nehme an, dass Sie etwas verwenden können, um ksh-Ausführung zu erzwingen. Die ps Optionen sind POSIX, also sollten sie portable-ish sein.

p.s. Wenn es einen besseren Weg dafür gibt, poste es bitte. Ich bin nicht stolz.