Trasferimento di variables d'ambiente tramite SSH / citazione in bash / sh / csh / tcsh

Voglio trasferire una variabile d'ambiente su SSH.

Il modo "corretto" utilizza SendEnv / ~/.ssh/environment , ma richiede che il server supporti AcceptEnv o PermitUserEnvironment, che non è nel mio caso.

Quindi invece sto pensando di impostare la variabile sul sito remoto come questo:

 FOO=val export FOO ssh server export FOO=$FOO'; do_stuff_which_uses_FOO' 

Quella parte è facile. Voglio una soluzione generica, quindi non import il contenuto di $ FOO functionrà. Per esempio

 FOO=" '\"" export FOO QFOO=`quote "$FOO"` # quote will return "\ \ \'\\\"" export QFOO ssh server export FOO=$QFOO'; do_stuff_which_uses_FOO' 

Questo funziona non import se la shell di invio o di ricezione è sh o bash.

Tuttavia, ho anche bisogno di lavorare per csh / tcsh. E non saprò in anticipo quale shell l'estremità ricevente è in esecuzione. Questo significa che devo codificare qualcosa che funziona sia in / bin / sh che in / bin / csh.

Finora sono riuscito a farlo funzionare per sh / bash:

 ssh server // followed by the below quoted eval `echo $SHELL | grep -E "/(t)?csh" > /dev/null && echo setenv FOO \\\ \\\ \\\\\'\\\\\" || echo export FOO=\\\ \\\ \\\\\'\\\\\";` ; echo "$FOO" 

Posso anche farlo funzionare per csh / tcsh (l'utente csh ha csh come login shell):

 ssh [email protected] // followed by the below quoted eval `echo $SHELL | grep -E "/(t)?csh" > /dev/null && echo setenv FOO \\\ \\\ \\\\\'\\\\\" || echo export FOO=\\\ \\\ \\\\\'\\\\\";` ; echo "$FOO" 

Se $ FOO è * o? funziona bene con BASH:

 ssh server eval\ \`echo\ \$SHELL\ \|\ grep\ -E\ \"/\(t\)\?csh\"\ \>\ /dev/null\ \&\&\ echo\ setenv\ FOO\ \\\\\\\\\\\*\\\;\ \|\|\ echo\ export\ FOO=\\\\\\\\\\\*\\\;\`\;echo\ \"\$FOO\"\ a; 

Ma fallisce con csh:

 ssh [email protected] eval\ \`echo\ \$SHELL\ \|\ grep\ -E\ \"/\(t\)\?csh\"\ \>\ /dev/null\ \&\&\ echo\ setenv\ FOO\ \\\\\\\\\\\*\\\;\ \|\|\ echo\ export\ FOO=\\\\\\\\\\\*\\\;\`\;echo\ \"\$FOO\"\ a; No match. FOO: Undefined variable. 

Sembra * e? rifiuta di essere citato.

Per rispondere a questa domanda la soluzione dovrebbe essere:

  • essere in grado di trasferire una variabile di ambiente al server remoto
  • non utilizzare SendEnv / AcceptEnv / PermitUserEnvironment
  • funziona non import se la shell di origine è sh / bash / csh / tcsh
  • funziona non import se la shell di destinazione è sh / bash / csh / tcsh
  • lavoro indipendentemente dal contenuto della variabile di ambiente. In modo specifico dovrebbe alless lavorare per: \ n * space '"? <>! $ \ E qualsiasi combinazione di quelle.

Se puoi trovare un modo migliore per trasferire la variabile che la cita, anche questo va bene.

Adesso ho un model di lavoro per tutti i caratteri eccetto \ n:

 sub shell_quote_scalar { # Quote the string so shell will not expand any special chars # Returns: # string quoted with \ as needed by the shell my $a = shift; $a =~ s/([\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\*\>\<\~\|\; \"\!\$\&\'\202-\377])/\\$1/g; $a =~ s/[\n]/'\n'/g; # filenames with '\n' is quoted using \' return $a; } sub env_quote { my $v = shift; $v =~ s/([ \n\&\<\>\(\)\;\'\{\}\t\"\$\`\*\174\!\?\~])/\\$1/g; return $v; } my @qcsh = map { my $a=$_; "setenv $a " . env_quote($ENV{$a}) } @vars; my @qbash = map { my $a=$_; "export $a=" . env_quote($ENV{$a}) } @vars; $Global::envvar = join"", (q{echo $SHELL | grep -E "/t?csh" > /dev/null && } . join(" && ", @qcsh) . q{ || } . join(" && ", @qbash) .q{;}); print shell_quote_scalar($Global::envvar); 

Puoi semplicemente basare64-codificare la variabile? Il modo più semplice per affrontare questo problema è probabilmente quello di trattare semplicemente i dati come binari.

 export QFOO=`echo $FOO | base64 --wrap=0` ssh server "export FOO=`echo \"$QFOO\" | base64 --decode --wrap=0`; <command>" 

Forse dovresti giocare con la citazione sulla linea ssh , ma questa è la chiave di ciò. Questo dovrebbe rimuovere le specifiche di shell per quanto riguarda la citazione, ma potrebbe introdurre alcuni con i comandi secondari (non ho molto familiarità con nulla al di fuori del bash )