2016-05-30 28 views
2

In einem script.sh,Ersetzen ‚Quelldatei‘ mit seinem Inhalt und Variablen in der Bash

source a.sh 
source b.sh 

CMD1 
CMD2 
CMD3 

erweitert, wie kann ich die source *.sh mit ihrem Inhalt ersetzen (ohne die Befehle ausgeführt wird)? Ich würde gerne sehen, was der Bash-Interpreter nach dem Sourcing der Dateien und der Erweiterung aller Variablen ausführt.

Ich weiß, ich kann set -n -v verwenden oder bash -n -v script.sh 2>output.sh ausführen, aber das würde die Quellbefehle nicht ersetzen (und noch weniger, wenn a.sh oder b.sh Variablen enthalten).

Ich dachte über die Verwendung einer Subshell, aber das erweitert noch nicht die Quellzeilen. Ich habe eine Kombination von set +n +v und set -n -v vor und nach den Quellzeilen versucht, aber das funktioniert immer noch nicht.

Ich werde diese Ausgabe an eine Remote-Maschine mit ssh senden. Ich könnte <<output.sh verwenden, um den Inhalt in den Befehl ssh zu pipen, aber ich kann nicht als root auf dem Remote-Rechner protokollieren, aber ich bin aber ein sudoer. Daher dachte ich, ich könnte das Skript erstellen und es als eine Base64-codierte Zeichenfolge (mit that clever trick) senden base64 script | ssh remotehost 'base64 -d | sudo bash'

Gibt es eine Lösung? Oder hast du eine bessere Idee?

Antwort

2

Sie können etwas tun:

inline.sh:

#!/usr/bin/env bash 
while read line; do 
    if [[ "$line" =~ (\.|source)\s+.+ ]]; then 
     file="$(echo $line | cut -d' ' -f2)" 
     echo "$(cat $file)" 
    else 
     echo "$line" 
    fi 
done < "$1" 

Hinweis dies setzt voraus, die source d Dateien vorhanden sind, und Fehler nicht behandeln. Sie sollten auch mit möglichen Hashbangs umgehen. Wenn die Dateien sourced sich selbst enthalten source, müssen Sie das Skript rekursiv anwenden, z. so etwas wie (nicht getestet):

while egrep -q '^(source|\.)' main.sh; do 
    bash inline.sh main.sh > main.sh 
done 

testen wir es

main.sh:

source a.sh 
. b.sh 

echo cc 
echo "$var_a $var_b" 

a.sh:

echo aa 
var_a="stack" 

b.sh:

echo bb 
var_b="overflow" 

Ergebnis:

bash inline.sh main.sh 

echo aa 
var_a="stack" 
echo bb 
var_b="overflow" 

echo cc 
echo "$var_a $var_b" 

bash inline.sh main.sh | bash 

aa 
bb 
cc 
stack overflow 

BTW, wenn Sie nur wollen, um zu sehen, was bash ausführt, können Sie

bash -x [script] 

oder remote

ssh [email protected] -t "bash -x [script]" 
+0

Haben Sie versucht, Ihre Lösung, wenn eine volle Funktionalität. Sh definiert eine Variable und main.sh ruft sie nach 'echo cc' auf? Ich glaube nicht, dass diese Variable erweitert wird. Und ja, ich weiß schon über die -x. Das Skript soll auf dem Remotecomputer ausgeführt werden, nicht meins, aber ich möchte es programmgesteuert schreiben (dh mit Variablen und einer Art Includes) –

+0

Die Antwort wurde aktualisiert. Der Wert muss nicht erweitert werden, wir brauchen nur seine Definition, um inline zu sein (es sei denn, die Quelldateien enthalten sich selbst als Quelle). Warum gibt es in diesem Fall einen Unterschied zwischen remote und local? Z.B. Sie können 'ssh user @ host -t" bash -x -c 'echo hi' "' verwenden – dimid