Wie kann ich Umgebungsvariablen für einen Remote-Rsync-Prozess festlegen?


12

Wenn ich mit rsync Dateien von einem Computer auf einen anderen kopiere, wird an beiden Enden ein rsync-Vorgang gestartet. Auf der Remote-Seite werden Shell-Initialisierungsdateien anscheinend nicht gelesen, sodass ich keine Umgebungsvariablen für den Remote-Rsync-Prozess einrichten kann. Leider gibt es einen Server, mit dem ich rsync muss, auf dem rsync eine Umgebungsvariable benötigt, um zu funktionieren. Ich bin kein Administrator auf dem Server, daher kann ich die globale Konfiguration nicht ändern. Was kann ich tun, um Umgebungsvariablen für einen Remote-Rsync-Prozess festzulegen?


Wie startet man den rsync-Prozess auf dem Server? Könnten Sie ein Skript über ssh auslösen?
Kraftan

Wenn Sie dies tun rsync localfilename remotehost:remotefilename, wird ein Rsync-Prozess auf dem Server gestartet. Ich weiß nicht genau, wie, aber es werden keine Shell-Initialisierungsdateien gelesen.
Ryan C. Thompson

Antworten:


19

~/.profilewird normalerweise nicht gelesen, wenn Sie ssh somecommandim Gegensatz zu einer interaktiven SSH-Sitzung (oder einer anderen Anmeldemethode, bei der Sie eine interaktive Sitzung starten) ausgeführt.

Ssh unterstützt das Senden von Umgebungsvariablen. Verwenden Sie in OpenSSH die SendEnvDirektive in ~/.ssh/config. Die spezifische Umgebungsvariable muss jedoch mit einer AcceptEnvDirektive in der Serverkonfiguration aktiviert werden , sodass dies für Sie möglicherweise nicht funktioniert.

OpenSSH ermöglicht auch das Setzen von Umgebungsvariablen auf der Serverseite. Auch dies muss in der Serverkonfiguration aktiviert werden, hier mit der PermitUserEnvironmentDirektive. Die Variablen können in der Datei eingestellt werden ~/.ssh/environment. Angenommen, Sie verwenden die Authentifizierung mit öffentlichem Schlüssel, können Sie auch Variablen pro Schlüssel festlegen, indem Sie ~/.ssh/authorized_keysFolgendes environment="FOO=bar"am Anfang der betreffenden Zeile einfügen.

Eine Sache, von der ich denke, dass sie (seltsamerweise) immer funktioniert, solange Sie die Authentifizierung mit öffentlichen Schlüsseln verwenden, ist, die command=Option in der authorized_keysDatei (ab) zu verwenden . Ein Schlüssel mit einer commandOption kann nur zum Ausführen des angegebenen Befehls verwendet werden. Der Befehl in der authorized_keysDatei wird jedoch mit der Umgebungsvariablen ausgeführt, SSH_ORIGINAL_COMMANDdie auf den vom Benutzer angegebenen Befehl festgelegt ist (leer für interaktive Sitzungen). So können Sie so etwas in verwenden ~/.ssh/authorized_keys(es gilt natürlich nicht, wenn Sie diesen Schlüssel nicht zur Authentifizierung verwenden):

command="export LD_LIBRARY_PATH=\"$HOME\"/lib;
         if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then
           eval \"$SSH_ORIGINAL_COMMAND\";
         else exec \"$SHELL\"; fi" ssh-rsa …

Beachten Sie, dass ich aus Gründen der Lesbarkeit Zeilenumbrüche oben angefügt habe, aber dies muss tatsächlich in einer Zeile erfolgen.

Eine andere Möglichkeit ist das Schreiben eines Wrapper-Skripts ~/bin/rsync-wrapperauf dem Server

#!/bin/sh
. ~/.profile
exec rsync "$@"

Dann geben Sie --rsync-path='bin/rsync-wrapper'die rsyncBefehlszeile weiter. Das Argument to --rsync-pathwird durch eine Shell erweitert. Wenn Sie es vorziehen, können Sie die rsync-Befehlszeile in sich geschlossen machen, indem Sie so etwas wie übergeben --rsync-path='. ~/.profile; rsync'.

Es gibt noch eine andere Möglichkeit, die davon abhängt, ob Ihre Anmeldeshell bash oder zsh ist. Bash liest immer, ~/.bashrcwenn es von rshd oder sshd aufgerufen wird, auch wenn es nicht interaktiv ist (aber nicht, wenn es als aufgerufen wird sh). Zsh liest immer ~/.zshenv.

## ~/.bashrc
if [[ $- != *i* ]]; then
  # Either .bashrc was sourced explicitly, or this is an rsh/ssh session.
  . ~/.profile
fi

## ~/.zshenv
if [[ $(ps -p $PPID -o comm=) = [rs]shd && $- != *l* ]]; then
  # Not a login shell, but this is an rsh/ssh session
  . ~/.profile
fi

Nun, das fasst es ziemlich gut zusammen. Ich hoffte, es gäbe einen besseren Weg als ein Wrapper-Skript.
Ryan C. Thompson

Aber warte eine Minute. Wie kann ich die rsync-Binärdatei auf dem Server finden, wenn meine Shell-Init-Dateien nicht gelesen werden? Ich habe in ~ / usr installiert, einem nicht standardmäßigen Speicherort, den ich $PATHin meinen Shell-Init-Skripten hinzufügen muss .
Ryan C. Thompson

@ Ryan: Ich hatte die direkteste Methode vergessen (siehe meine Bearbeitung), aber es erfordert auch eine Direktive, die in der Serverkonfiguration aktiviert ist. Wenn Sie eine Möglichkeit gefunden haben, dies PATHzu berücksichtigen, sollten Sie in der Lage sein, dort eine andere Variable festzulegen. (Wenn dies nicht funktioniert, versuchen Sie, ausgehend von einem set -xbeliebigen Shell-Skript so viele Traces wie möglich hinzuzufügen . Ersetzen Sie die rsyncBinärdatei durch ein Wrapper-Skript, das die Umgebung in eine Datei kopiert und dann die echte Binärdatei aufruft.)
Gilles 'SO - Hör auf, böse zu sein '

Was ist ~/.ssh/rc?
Ryan C. Thompson

@Ryan: ~/.ssh/rcwird von einem separaten Shell-Prozess ausgeführt. Ich denke, Ihre beste Wette ist ein Wrapper-Skript oder --rsync-path='. ~/.profile; rsync'. Oder kompilieren Sie rsyncmit einem geeigneten Pfad gemäß Ihrer anderen Frage.
Gilles 'SO- hör auf böse zu sein'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.