it-swarm.com.de

Kann scp ein Verzeichnis erstellen, wenn es nicht existiert?

Ich möchte scp verwenden, um Dateien hochzuladen, aber manchmal ist das Zielverzeichnis möglicherweise nicht vorhanden.

Ist es möglich, den Ordner automatisch zu erstellen? Wenn das so ist, wie? Wenn nicht, welchen alternativen Weg kann ich versuchen?

100
AGamePlayer

Dies ist eines der vielen Dinge, die rsync tun kann.

Wenn Sie eine Version von rsync verwenden, die in den letzten Jahren veröffentlicht wurde, ähnelt ¹ die grundlegende Befehlssyntax der von scp: ²

$ rsync -r local-dir remote-machine:path

Dadurch werden local-source Und sein Inhalt nach $HOME/path/local-dir Auf dem Remotecomputer kopiert und alle erforderlichen Verzeichnisse erstellt.³

rsync hat hier einige Einschränkungen, die sich darauf auswirken können, ob dies in Ihrer speziellen Situation funktioniert. Es werden beispielsweise nicht mehrere Ebenen fehlender Remote-Verzeichnisse erstellt. Es werden nur bis zu einer fehlenden Ebene auf der Fernbedienung erstellt. Sie können dies leicht umgehen, indem Sie dem Befehl rsync Folgendes vorangestellt haben:

$ ssh remote-Host 'mkdir -p foo/bar/qux'

Dadurch wird der Baum $HOME/foo/bar/qux Erstellt, wenn er nicht vorhanden ist. Es wird sich nicht beschweren oder etwas anderes Schlechtes tun, wenn es tut bereits existiert.

rsync hat manchmal andere überraschende Verhaltensweisen. Grundsätzlich bitten Sie es, herauszufinden, was Sie kopieren wollten, und seine Vermutungen stimmen möglicherweise nicht mit Ihren Annahmen überein. Probieren Sie es aus und sehen Sie. Wenn es sich nicht wie erwartet verhält und Sie nicht verstehen, warum, veröffentlichen Sie weitere Details zu Ihren lokalen und Remote-Verzeichnis-Setups und geben Sie den Befehl ein, den Sie versucht haben.


Fußnoten :

  1. Vor rsync 2.6.0 (1. Januar 2004) war das Flag -e ssh Erforderlich, damit es sich wie scp verhält, da standardmäßig veraltet RSH-Protokoll .

  2. scp und rsync teilen sich einige Flags, aber es gibt nur eine kleine Überlappung.

  3. Bei Verwendung von SSH als Übertragungsprotokoll verwendet rsync dieselben Standardeinstellungen. Genau wie bei scp wird daher davon ausgegangen, dass sich standardmäßig ein Benutzer mit demselben Namen wie Ihr lokaler Benutzer auf dem Remotecomputer befindet.

76
Warren Young

Wenn Sie eine Gruppe von Dateien kopieren, nicht wirklich. Wenn Sie ein Verzeichnis und den gesamten Inhalt darunter kopieren, ja. Angesichts dieses Befehls:

$ scp -pr /source/directory [email protected]:the/target/directory

Wenn directory in ~/the/target Unter Host nicht vorhanden ist, wird es erstellt. Wenn jedoch ~the/target Nicht vorhanden ist, treten wahrscheinlich Probleme auf. Ich erinnere mich nicht an die genauen Ergebnisse dieses Falls, bin jedoch darauf vorbereitet, dass das beabsichtigte scp fehlschlägt.

39
John

Soweit ich weiß, kann scp das selbst nicht, nein. Sie können jedoch einfach ssh auf den Zielcomputer senden, das Verzeichnis erstellen und dann kopieren. Etwas wie:

ssh [email protected] "mkdir -p /target/path/" &&
    scp /path/to/source [email protected]:/target/path/

Beachten Sie, dass beim Kopieren ganzer Verzeichnisse das oben Gesagte nicht benötigt wird. Um beispielsweise das Verzeichnis ~/foo Auf den Remote-Host zu kopieren, können Sie das Flag -r (Rekursiv) verwenden:

scp ~/foo/ [email protected]:~/

Dadurch wird das Zielverzeichnis ~/foo Auf dem Remote-Host erstellt. Das übergeordnete Verzeichnis kann jedoch nicht erstellt werden. scp ~/foo [email protected]:~/bar/foo Schlägt fehl, es sei denn, das Zielverzeichnis bar existiert. In jedem Fall hilft das Flag -r Nicht beim Erstellen eines Zielverzeichnisses, wenn Sie einzelne Dateien kopieren.

17
terdon

Ich benutze die folgende Funktion, bevor ich btrfs Schnappschüsse über ssh übertrage:

check_remote_dir() {
        printf "\ntesting remote directory: '$1' "

        if ssh -p $PORT [email protected]$REMOTE "[ ! -d $1 ]"; then
                printf "\nCreating: $1 on [email protected]$REMOTE\n"
                ssh -p $PORT [email protected]$REMOTE "mkdir -p $1"
        else
                printf "[OK]\n"
        fi
}

Rufen Sie einfach die Funktion in Ihrem Skript auf mit:

check_remote_dir /my/remote/path

4
Stuart Cardall

Ja, du kannst. Laut der Manpage von scp:

man scp

..... .....

-r Kopiert rekursiv ganze Verzeichnisse. Beachten Sie, dass scp symbolischen Verknüpfungen folgt, die beim Durchlaufen des Baums auftreten.

....

3
YoMismo

Wenn nur scp oder sftp ohne ssh verfügbar ist (per rssh), können Verzeichnisse erstellt werden, indem der leere Verzeichnisbaum mit rsync kopiert und anschließend Dateien kopiert werden.

So lege ich den öffentlichen SSH-Schlüssel auf den Remote-Host, wenn die SSH-Copy-ID nicht funktioniert und das SSH-Verzeichnis nicht vorhanden ist:

rsync -e 'ssh -p22' -av -f"+ */" -f"- *" ~/.ssh [email protected]:~/
scp -P22 ~/.ssh/id_rsa.pub [email protected]:~/.ssh/authorized_keys

Es ist möglich, diese Befehle zu einem Rsync zu kombinieren und einen weiteren Include-Filter in der Mitte hinzuzufügen, wenn der Name der Zieldatei identisch ist.

1
user3132194

Sie können den Befehl mit dem Befehl mkdir verketten und dann auf den von Ihnen erstellten Ordner verweisen:

mkdir ~/new-folder/ && scp -P 22 <remote/url>:~/new-folder/
0
Ducky

Wie wäre es mit "smart" scp + ssh mkdir?

Dies ist ein Skript zum Erstellen einer Zielverzeichnishierarchie nur einmal pro Verzeichnis (kein blindes ssh mkdir -p jedes Mal).

Begründung

Ich kopiere Bewegungsaufzeichnungen (Videodateien), während sie auf die lokale Festplatte geschrieben werden (ereignisgesteuert).

  • rsync macht keinen Sinn, da es keinen Sinn macht, vollständige Verzeichnisvergleiche durchzuführen - ich übertrage eine Datei pro Ereignis. Wenn ich rsync auf nur ein Unterverzeichnis oder eine Datei beschränke, kann nicht die vollständige Zielverzeichnishierarchie erstellt werden.
  • scp wird gut funktionieren, aber es weiß nicht, ob das Zielverzeichnis existiert, und ich möchte nicht für jede Datei ein ssh mkdir -p ausführen.

Lösung

  1. Erstellen Sie jedes Zielverzeichnis über ssh, wenn es zum ersten Mal benötigt wird (zum ersten Mal, wenn wir es kopieren).
  2. Cache den Namen des Zielverzeichnisses in einem Array, damit wir nicht ssh mkdir jedes Mal, wenn wir es wieder sehen. Löschen Sie dieses Array täglich, damit es nicht riesig wird.
  3. scp die Datei.

Beispielcode:

#!/bin/bash

TARGETHOST="some.hostname"
TARGETPATH="/data/backups/MOTION/"

ensure_dir() {
    if [ "$TODAY" != "$(date +%D)" ] ; then
        CREATED=()  # reset array daily and first time so it won't get huge
        TODAY=$(date +%D)
    fi  
    if [[ ! " ${CREATED[@]} " =~ " ${1} " ]]; then
        # create dir
        echo "Creating remote directory: $1"
        ssh $TARGETHOST "mkdir -p ${TARGETPATH}$1"
        CREATED+=("$1")
    fi  
}

# This line is specific to my use case, watching a directory for new files:
inotifywait -mr --format '%w %f' -e close_write --exclude '.jpg' /data/MOTION/ | while read filedir filename ; do
    RELDIR=$(echo $filedir | sed 's|/data/MOTION/||')
    ensure_dir "$RELDIR"
    echo "Copying '$filename' from '${filedir}' to '${RELDIR}'"
    scp -r -p "${filedir}${filename}" "${TARGETHOST}:${TARGETPATH}${RELDIR}${filename}"
done

Typische Ausgabe, die das "intelligente" Verhalten von mkdir veranschaulicht:

Creating remote directory: 2019-12-28/movie-C6/
Copying 'test1.mp4' from '/data/MOTION/2019-12-28/movie-C6/' to '2019-12-28/movie-C6/'
Creating remote directory: 2019-12-28/movie-C4/
Copying '095700.mp4' from '/data/MOTION/2019-12-28/movie-C4/' to '2019-12-28/movie-C4/'
Copying '095841.mp4' from '/data/MOTION/2019-12-28/movie-C4/' to '2019-12-28/movie-C4/'
Copying '100410.mp4' from '/data/MOTION/2019-12-28/movie-C4/' to '2019-12-28/movie-C4/'
Creating remote directory: 2019-12-28/movie-C2/
Copying '102106.mp4' from '/data/MOTION/2019-12-28/movie-C2/' to '2019-12-28/movie-C2/'
Creating remote directory: 2019-12-28/movie-C5/
Copying '102318.mp4' from '/data/MOTION/2019-12-28/movie-C5/' to '2019-12-28/movie-C5/'
Copying '102326.mp4' from '/data/MOTION/2019-12-28/movie-C2/' to '2019-12-28/movie-C2/'
Creating remote directory: 2019-12-28/movie-C1/
Copying '102450.mp4' from '/data/MOTION/2019-12-28/movie-C1/' to '2019-12-28/movie-C1/'
Copying '102744.mp4' from '/data/MOTION/2019-12-28/movie-C2/' to '2019-12-28/movie-C2/'
Copying '103008.mp4' from '/data/MOTION/2019-12-28/movie-C2/' to '2019-12-28/movie-C2/'
Copying '103945.mp4' from '/data/MOTION/2019-12-28/movie-C6/' to '2019-12-28/movie-C6/'
Copying '104252.mp4' from '/data/MOTION/2019-12-28/movie-C6/' to '2019-12-28/movie-C6/'
Copying '104824.mp4' from '/data/MOTION/2019-12-28/movie-C6/' to '2019-12-28/movie-C6/'
0
Akom