2014-04-15 6 views
5

Ich bin ein Problem unter Befehl ausführen bekommen:Shell-Funktion Problem - den Apostroph aus der Shell-Anweisung

wenn ich laufe: cmssh 12np, ich meinte die definierte Funktion cmssh aufzurufen, schließlich ich einen Shell-Befehl erwarte Zeile wie folgt aus:

sshpass -p password ssh mydomain\\[email protected] 

, unter Quelle sehen:

alias 12np='ssh mydomain\\[email protected]@host.com' 


function cmssh() { 
    set -x 
    local aliascmd=$1 
    cmdstr=$(alias $aliascmd | cut -d'=' -f2 | cut -d"'" -f2) 
    echo $cmdstr 
    sshpass -p "$cmpw" $cmdstr 
    #debug cmdstr : sshpass -p password 'ssh mydomain\\[email protected]' 
} 

der letzte Schritt immer machen jedoch das Ergebnis als:

sshpass -p password 'ssh mydomain\\[email protected]' 

Ich habe versucht viele Möglichkeiten zu versuchen, das einfache Zitat zu entfernen, aber habe keine Ahnung, wie es möglich ist.

Siehe die Debug-Informationen:

~ cmssh 12np 
+cmssh:2> local 'aliascmd=12np' 
+cmssh:4> cmdstr=+cmssh:4> alias 12np 
+cmssh:4> cmdstr=+cmssh:4> cmdstr=+cmssh:4> cut '-d=' -f2 
+cmssh:4> cut '-d'\' -f2 
+cmssh:4> cmdstr='ssh mydomain\\[email protected]' 
+cmssh:7> echo 'ssh mydomain\\[email protected]' 
ssh mydomain\\[email protected] 
+cmssh:8> sshpass -p password 'ssh mydomain\\[email protected]' 
sshpass: Failed to run command: No such file or directory 

Dank

+0

Gibt es Sonderzeichen in Ihrem Passwort? Wenn Sie Ihr Passwort in '$ cmpw' speichern und' sshpass -p "$ cmpw" ssh mydomain \\ userxyz @ host.com' in der Befehlszeile ausführen, wird es dann erfolgreich ausgeführt? –

+0

Welche Shell führt das aus? Sieht aus wie 'Bash', aber bitte bestätigen. – mklement0

Antwort

1

Hinweis sed Verwendung: Bei dieser Punkt ist es nicht Deaktivieren Sie, welche spezifische Shell das OP verwendet. Diese Antwort macht einen allgemeinen Punkt und diskutiert dann bash und zsh.

Ihr sofort Problem ist, nichts zu tun zu zitieren: Die Fehlermeldung deutet darauf hin, dass die ausführbaren sshpass ist nicht in Ihrem $PATH.

Ihre string ($cmdstr) eigentlich nicht einfache Anführungszeichen enthalten - sie sind ein Artefakt vonbash oder zsh mit set -x in Kraft läuft.

Allerdings gibt es weitere Probleme:


Die Art und Weise Sie die Alias-Definition in cmssh() schaltet die \\ in Ihrem Alias-Definition aus einem (konzeptuell) zitierte einzelne\ in Zeichenkette analysieren \\ (zwei Literal Zeichen.)

Eine einfache Lösung in diesem Fall ist, eine weitere Bewertungsschicht hinzuzufügen, indem Sie xargs (ohne Argumente) die Zeichenfolge echo:

cmdstr=$(alias $aliascmd | cut -d"'" -f2 | xargs) 

Bitte beachte, dass ich die = -basierte cut Befehl beseitigt haben, die nicht benötigt wird.

Im Allgemeinen ist das Parsen von Aliasdefinitionen jedoch fragil.

An diesem Punkt würde ich erwarten, dass Ihr Code in bash funktioniert, aber noch nicht in zsh (siehe unten). Beachten Sie, dass das Entfernen des Codes function  am Anfang der Funktionsdefinition Ihren Code auch in sh (eine POSIX-features-only-Shell) funktionieren lässt.


Das letzte Problem betrifft nur zsh, nicht bash:

zsh nicht standardmäßig Wort Spaltung auf $cmdstr im sshpass -p "$cmpw" $cmdstr Befehl nicht ausführen, so dass 'ssh mydomain\[email protected]' als ein einziges Argument zu sshpass geben wird.

Um auf einzelne Wörter aufgespalten drehen, wenn $cmdstr Auswertung und damit seine Tokens als separate Argumente übergeben, bezeichnen es als ${=cmdstr}:

sshpass -p "$cmpw" ${=cmdstr} 

Beachten Sie, dass diese Funktion zsh -spezifische ist.

+0

Diese Lösung hat funktioniert. Ja, es ist in zsh. Und deine Antwort ist großartig. Ich verbrachte einen Tag damit und war mir bewusst, was das Problem ist. Vielen Dank. Könnten Sie helfen, bash und zsh etwas zu unterstützen, indem Sie dort eine Bedingungslogik hinzufügen: wie Funktion cmssh() { local aliascmd = $ 1 cmdstr = $ (alias $ aliascmd | cut -d "'" -f2 | xargs ) if (es zsh ist): sshpass -p "$ cmpw" $ {= cmdstr} anderes: sshpass -p "$ cmpw" $ cmdstr } Vielen Dank –

+0

Ok, ich es herausfinden, exportiere ich ein Variabel zB WHICH_SHELL = "BASH" für die Laufzeit zu erkennen. Es klappt. –

+0

@stephencheng: Freut mich zu hören; Sie können sich tatsächlich auf Variablen verlassen, die 'bash' und' zsh' automatisch definieren: 'bash' definiert' $ BASH_VERSION' (unter anderem) und 'zsh' definiert' $ ZSH_VERSION'. Zum Beispiel ist '[[-n $ BASH_VERSION]]' nur in 'bash' wahr. – mklement0

0

dieses Versuchen

mydomain="'ssh mydomain\\[email protected]'" 

echo ${mydomain/#'/\\\'} \\ assign this variable 

Andere Art und Weise, dies zu tun,

echo $mydomain | sed -s "s/^\(\(\"\(.*\)\"\)\|\('\(.*\)'\)\)\$/\\3\\5/g"