Bash 管道:在第一行之后分割输入,在第一行和其余行上运行不同的命令

发布于 2025-01-04 20:54:56 字数 1095 浏览 3 评论 0原文

我有一个备份脚本,它通过 ssh 复制文件并在传输过程中创建哈希文件。另外 pv 用于显示进度条:

ssh $host "cat '$src_dir/$filename'" \
    | pv --bytes --eta --progress --rate --timer --wait  $opts \
    | tee "$filename" \
    | sha1sum > "$filename.sha1"

为了正确显示进度条,我需要将文件的大小传递给 pv。目前我通过给出最后一个备份文件的大小来做到这一点。

重要的是,一切都通过 1 次 ssh 调用完成,因为我不想为 1 次备份授权多次。 SSH 密钥正在使用中,但使用密码进行保护。

我的想法是调用 ssh $host "stat -c%s '$src_dir/$filename'; cat '$src_dir/$filename'" 并在第一行之后分割输出。我可以读取文件大小,然后对其余输入调用 pv

备份脚本工作正常。这只是一个为了好玩的练习。任何想法都值得赞赏,但我不会完全重写整个脚本。特别是我不会切换到 scp 因为我无法在传输过程中进行哈希处理,而且我不想信任本地存储(当然我愿意,但是为什么我们要这样做)无论如何都要进行哈希处理吗?)。

更新:我最终这样做了:

ssh $host "cd '$src_dir' && stat -c%s '$filename' && sha1sum '$filename' && cat '$filename'" | {
        read size;
        head -n 1 > "$filename.sha1";
        pv --bytes --eta --progress --rate --size $size --timer --wait > "$filename"
    }

它工作完美,并且具有哈希值在远程站点计算的优点。因此,不仅在写入磁盘之前,而且在进行网络传输之前。

I have a backup script which copies a file via ssh and creates a hash file during transfer. Additionally pv is used to display a progress bar:

ssh $host "cat '$src_dir/$filename'" \
    | pv --bytes --eta --progress --rate --timer --wait  $opts \
    | tee "$filename" \
    | sha1sum > "$filename.sha1"

To display the progress bar correctly I need to pass the size of the file to pv. At the moment I do that by giving the size of the last backup file.

It is important that everything is done with 1 ssh call because I don't want to authorize multiple times for 1 backup. SSH keys are in use but secured with a passphrase.

My idea is to call ssh $host "stat -c%s '$src_dir/$filename'; cat '$src_dir/$filename'" and split the output after the 1st line. I could read the filesize and then call pv on the rest of the input.

The backup script is working fine. This is just an exercise for the fun of it. Any ideas are appreciated but I will not completely rewrite the whole script. Especially I won't switch to scp because I can't do the hashing during transfer then and I don't want to trust the local storage for that (of course I do, but then why do we do hashing anyway?).

Update: I ended up doing this:

ssh $host "cd '$src_dir' && stat -c%s '$filename' && sha1sum '$filename' && cat '$filename'" | {
        read size;
        head -n 1 > "$filename.sha1";
        pv --bytes --eta --progress --rate --size $size --timer --wait > "$filename"
    }

It works perfectly and has the advantage that the hash is computed at the remote site. So not only before writing to disk but before doing the network transfer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦里的微风 2025-01-11 20:54:56

在此示例中,我在 OSX 上使用 stat,它使用 z 作为大小的格式字符串:

$ { stat -f %z input; cat input; } | { read s; echo $s; }

将第一个命令列表替换为您的 ssh 调用,并将 echo 替换为您的 pv 列表,然后就可以开始了。换句话说,您的最终命令应该是:

$ ssh $host "stat -c%s '$src_dir/$filename'; cat '$src_dir/$filename'" | {
    read size;
    pv --bytes --eta --progress --rate --timer --wait --size $size |
    tee "$filename" |
    sha1sum; } > "$filename.sha1"

我有几件事需要注意:我无权访问 pv 并且没有检查上述内容。
我用管道符号替换了你的续行,因为我认为
它看起来更好。

另一个想法:在管道的右侧,您可以这样做:

{ pv --bytes ... --size $( sed 1q ) |
...

这绝对依赖于 sed 不读取第一个换行符,我不知道是否有任何标准保证这一点,但它适用于...哦天哪,我的 sed 不支持 --version、-? 或 -h,而且我不太了解 OS X 的包管理系统,无法告诉你我正在运行什么 sed。它适用于某些版本的 BSD sed...

In this example, I use stat on OSX, which uses z for the format string for size:

$ { stat -f %z input; cat input; } | { read s; echo $s; }

Replace the first command list with your ssh call, and replace the echo with you pv list, and you are good to go. In other words, your final command should be:

$ ssh $host "stat -c%s '$src_dir/$filename'; cat '$src_dir/$filename'" | {
    read size;
    pv --bytes --eta --progress --rate --timer --wait --size $size |
    tee "$filename" |
    sha1sum; } > "$filename.sha1"

I few things to note: I don't have access to pv and did not check the above.
I replaced your line continuations with pipe symbols, because I think
it looks nicer.

Another idea: on the right hand side of the pipe, you could do:

{ pv --bytes ... --size $( sed 1q ) |
...

This definitely relies on sed not reading past the first newline, and I do not know if that is guaranteed by any standard, but it works with ... oh my, my sed does not support --version, -?, or -h, and I do not know the package management system of OS X well enough to tell you what sed I'm running. It works with some version of BSD sed...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文