我想以图形方式显示从远程服务器到本地机器的几个文件的 scp 传输进度。
我以为可以使用 Zenity 来举例。浏览网络后,我发现可以使用命令 pv 来执行此操作。
类似这样的:
(
scp user@remote:/home/folder/* . | pv -n -b -s $totalSize
) | zenity --progress --title="Transfer window" --percentage=0 --auto-close
但这不起作用。
使用 rsync 可能是一种替代方法。
任何想法?
谢谢。
答案1
您的问题在于 zenity 需要逐行输入数字和注释。您使用“-b”标志发送了更多内容。请尝试将其删除,然后重试。
Zenity 逐行从标准输入读取数据。如果某行以 # 为前缀,则文本将使用该行上的文本进行更新。如果某行仅包含数字,则百分比将使用该数字进行更新。
仅使用 SCP
现在,您似乎想要某种进度视图。我会尝试 scp 的详细标志,它应该可以解决问题:
scp -v user@remote:/home/folder/* .
我不确定您想在那里完成什么,但您可能希望在复制命令和压缩中包含子文件夹以减少传输时间,如下所示:
scp -vrC user@remote:/home/folder/* .
使用 Rsync
如果我是你,我会使用 rsync 来实现这一点,它可以进行增量复制以及保留权限和时间等许多其他操作。以下是我经常使用的一些命令:
不删除本地文件的增量复制
rsync -avz --progress user@remote:/home/folder/ ./
增量复制制作两个目录的镜像,删除远程服务器上不存在的文件
rsync -avz --delete --progress user@remote:/home/folder/ ./
答案2
不幸的是,如果 stdout 不是终端,scp 就不会显示进度。
您有 2 个选择:
选项1修改 scp 代码以忽略 stdout 不是终端的情况。下载源代码(来自http://www.openssh.com/)
在 scp.c:main() 中注释以下代码
if (!isatty(STDOUT_FILENO))
showprogress = 0;
选项 2使用包装器,欺骗 scp 认为有一个终端。
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
main(int argc, char **argv) {
int fd;
pid_t pid;
char c,c1,c2;
if (argc != 3) {
printf("usage: [[user@]host1:]file1 [[user@]host2:]file2\n\nThis is a program that wraps scp and prints out the numeric progress on separate lines.\n");
fflush(stdout);
_exit(1);
}
pid = forkpty (&fd, NULL, NULL, NULL);
if (pid == 0) {
execlp ("scp", "scp", argv[1], argv[2], (char *) NULL);
_exit (1);
} else if (pid == -1) {
return 1;
} else {
FILE *F;
F = fdopen (fd, "r");
//reading character by character isn't horribly efficient...
while((c = fgetc(F)) != -1) {
if (c == '%') {
if (c1 == ' ')
printf("%c\n", c2); //one digit progess
else if (c1 == '0' && c2 == '0')
printf("100\n"); //done
else
printf("%c%c\n", c1,c2); //two digit progress
}
fflush(stdout);
c1 = c2;
c2 = c;
}
fflush (F);
wait (0);
}
return 0;
}
编译包装器并使用它来 scp
$ ./scpwrap /home/ubuntu/somefile [email protected]:~ | zenity --progress
原始解决方案及更多详细信息来自:http://blog.clay.shep.me/2009/06/showing-scp-progress-using-zenity.html