![Verwenden von pv(1) zur Begrenzung der Rsync-Geschwindigkeit](https://rvso.com/image/1414685/Verwenden%20von%20pv(1)%20zur%20Begrenzung%20der%20Rsync-Geschwindigkeit.png)
Ich versuche, pv
anstelle des integrierten rsync-Befehls --bwlimit
die Bandbreite eines rsync-Transfers zu begrenzen, da --bwlimit
dieser auf eine letztendlich konsistente Weise implementiert ist und meine Transfers so kurz sind, dass die Begrenzung nie wirklich greift. Diesfastfunktioniert, aber das System wird nicht ordnungsgemäß beendet.
Für diejenigen, die es nicht kennen: pv
Es handelt sich um das Dienstprogramm Pipe-Viewer. Es verfügt jedoch über eine wenig bekannte Funktion zur Begrenzung der Datenrate, die durch eine Pipe fließt.
Bearbeiten, um hinzuzufügen: Ich glaube, ich habe das Grundproblem gefunden. Normalerweise stoppt ein Prozess in einer Pipeline entweder, weil a) der stdin geschlossen wird oder b) er beim Schreiben in stdout SIGPIPE erhält. Keines von beidem passiert, weil a) rsync den Socket auf stdin (anscheinend) nie schließt und b) es nie versucht, in stdout zu schreiben, weil rsync das Senden von Daten auf stdin im selben Moment beendet, in dem stdout geschlossen wird.
Was ich brauche, ist eine Art Wrapping-Befehl, der dafür sorgt, dass pv heruntergefahren wird, sobald stdout geschlossen wird, unabhängig davon, ob stdin noch Daten sendet.
Demonstration:
head -c 100000 /dev/urandom > random4.bin
ls -lh random4.bin
> -rw-r--r-- 1 buck users 98K 2014-07-07 11:01 random4.bin
export RSYNC_RSH='sh -c '\''pv -qL10k | ssh "$@" | pv -qL11k'\'' ssh'
rsync -av --progress localhost:$PWD/random4.bin random5.bin
> receiving incremental file list
> random4.bin
> 100000 100% 17.47kB/s 0:00:05 (xfer#1, to-check=0/1)
>
> sent 30 bytes received 100109 bytes 10540.95 bytes/sec
> total size is 100000 speedup is 1.00
> (never exits)
An diesem Punkt muss ich Strg-C drücken, um die Kontrolle über mein Terminal zurückzuerlangen. Das Problem besteht darin, dass das pv
am Eingang von SSH sitzende Skript nie beendet wird, obwohl sein Ausgang geschlossen wurde.
Ein bisschen Debuggen:
pstree -lap 29532
> rsync,29532 -av --progress localhost:/nail/home/buck/tmp/random4.bin random5.bin
> └─sh,29533 -c pv -qL10k | ssh "$@" | pv -qL11k ssh localhost rsync --server --sender -vlogDtpre.iLsf . /nail/home/buck/tmp/random4.bin
> └─pv,29534 -qL10k
lsof -p 29532
> COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
> rsync 29532 buck cwd DIR 252,0 4096 7345851 /nail/home/buck/tmp
> rsync 29532 buck rtd DIR 9,1 4096 2 /
> rsync 29532 buck txt REG 9,1 405368 94575 /usr/bin/rsync
> rsync 29532 buck mem REG 9,1 51712 554006 /lib/libnss_files-2.11.1.so
> rsync 29532 buck mem REG 9,1 43552 553997 /lib/libnss_nis-2.11.1.so
> rsync 29532 buck mem REG 9,1 97256 553992 /lib/libnsl-2.11.1.so
> rsync 29532 buck mem REG 9,1 35712 553831 /lib/libnss_compat-2.11.1.so
> rsync 29532 buck mem REG 9,1 18704 553802 /lib/libattr.so.1.1.0
> rsync 29532 buck mem REG 9,1 1584520 554000 /lib/libc-2.11.1.so
> rsync 29532 buck mem REG 9,1 44008 554064 /lib/libpopt.so.0.0.0
> rsync 29532 buck mem REG 9,1 31208 553800 /lib/libacl.so.1.1.0
> rsync 29532 buck mem REG 9,1 136936 554003 /lib/ld-2.11.1.so
> rsync 29532 buck mem REG 9,1 256324 172607 /usr/lib/locale/en_US.utf8/LC_CTYPE
> rsync 29532 buck mem REG 9,1 26048 93726 /usr/lib/gconv/gconv-modules.cache
> rsync 29532 buck 0u CHR 136,10 0t0 13 /dev/pts/10
> rsync 29532 buck 1u CHR 136,10 0t0 13 /dev/pts/10
> rsync 29532 buck 2u CHR 136,10 0t0 13 /dev/pts/10
> rsync 29532 buck 3u unix 0xffff882026de4100 0t0 349807593 socket
> rsync 29532 buck 4u unix 0xffff880d79016e80 0t0 349851596 socket
lsof -p 29533
> COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
> sh 29533 buck cwd DIR 252,0 4096 7345851 /nail/home/buck/tmp
> sh 29533 buck rtd DIR 9,1 4096 2 /
> sh 29533 buck txt REG 9,1 101608 504936 /bin/dash
> sh 29533 buck mem REG 9,1 1584520 554000 /lib/libc-2.11.1.so
> sh 29533 buck mem REG 9,1 136936 554003 /lib/ld-2.11.1.so
> sh 29533 buck 0u unix 0xffff880d79014100 0t0 349851595 socket
> sh 29533 buck 1u unix 0xffff880d79014e00 0t0 349851598 socket
> sh 29533 buck 2u CHR 136,10 0t0 13 /dev/pts/10
lsof -p 29534
> COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
> pv 29534 buck cwd DIR 252,0 4096 7345851 /nail/home/buck/tmp
> pv 29534 buck rtd DIR 9,1 4096 2 /
> pv 29534 buck txt REG 9,1 35336 106025 /usr/bin/pv
> pv 29534 buck mem REG 9,1 1584520 554000 /lib/libc-2.11.1.so
> pv 29534 buck mem REG 9,1 136936 554003 /lib/ld-2.11.1.so
> pv 29534 buck mem REG 9,1 256324 172607 /usr/lib/locale/en_US.utf8/LC_CTYPE
> pv 29534 buck mem REG 9,1 54 172608 /usr/lib/locale/en_US.utf8/LC_NUMERIC
> pv 29534 buck mem REG 9,1 2454 172707 /usr/lib/locale/en_US.utf8/LC_TIME
> pv 29534 buck mem REG 9,1 1170770 172610 /usr/lib/locale/en_US.utf8/LC_COLLATE
> pv 29534 buck mem REG 9,1 286 172708 /usr/lib/locale/en_US.utf8/LC_MONETARY
> pv 29534 buck mem REG 9,1 57 172710 /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
> pv 29534 buck mem REG 9,1 34 172614 /usr/lib/locale/en_US.utf8/LC_PAPER
> pv 29534 buck mem REG 9,1 77 172615 /usr/lib/locale/en_US.utf8/LC_NAME
> pv 29534 buck mem REG 9,1 155 172711 /usr/lib/locale/en_US.utf8/LC_ADDRESS
> pv 29534 buck mem REG 9,1 59 172712 /usr/lib/locale/en_US.utf8/LC_TELEPHONE
> pv 29534 buck mem REG 9,1 23 172618 /usr/lib/locale/en_US.utf8/LC_MEASUREMENT
> pv 29534 buck mem REG 9,1 26048 93726 /usr/lib/gconv/gconv-modules.cache
> pv 29534 buck mem REG 9,1 373 172713 /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
> pv 29534 buck 0u unix 0xffff880d79014100 0t0 349851595 socket
> pv 29534 buck 1w FIFO 0,8 0t0 349847461 pipe
> pv 29534 buck 2u CHR 136,10 0t0 13 /dev/pts/10
Antwort1
Es scheint, dass pv
auf Daten von wartet rsync
und rsync
ebenfalls auf Daten wartet (steckt in fest select()
) und die Eingabe in nicht schließt pv
. Es handelt sich also um einen Deadlock. Dasselbe passiert, wenn Sie pv
durch etwas anderes ersetzen (wie dd
). Es scheint, dass sich diese Befehle einfach nicht so verhalten, wie rsync
man es erwartet.
Ich habe keine Problemumgehung gefunden, außer alles zu beenden:
export RSYNC_RSH="sh -c 'pv -qL10k | ssh \"\$@\" | (pv -qL11k; kill \$\$)' ssh"
kill
ist keine Lösung, mit der ich zufrieden wäre. Aber ich habe keine andere gefunden.
Natürlich $$
war die Verwendung der bequemere Ausweg, man sollte pv
stattdessen kill verwenden, aber wie erhält man die PID in einem Oneliner? pidof
Gibt einfach beliebige pv
PIDs aus. Die Abfrage ihrer jeweiligen übergeordneten PIDs schien für einen Oneliner etwas seltsam.
Ich freue mich auf eine echte Lösung... ;)