bash 如何 scp 文件并运行 ssh 命令只要求输入一次密码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6268713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:08:14  来源:igfitidea点击:

How can I scp a file and run an ssh command asking for password only once?

linuxbashsshscp

提问by cledoux

Here's the context of the question:

这是问题的上下文:

In order for me to be able to print documents at work, I have to copy the file over to a different computer and then print from that computer. (Don't ask. It's complicated and there is not another viable solution.) Both of the computers are Linux and I work in bash. The way I currently do this is I scpthe file over to the print computer and then sshin and print from command line.

为了能够在工作中打印文档,我必须将文件复制到另一台计算机,然后从该计算机打印。(不要问。这很复杂,而且没有其他可行的解决方案。)两台计算机都是 Linux,我在 bash 中工作。我目前这样做的方法是scp将文件传输到打印计算机,然后ssh从命令行输入并打印。

Here's what I would like to do:

这是我想做的事情:

In order to make my life a bit easier, I'd like to combine these two step into one. I could easily write a function that did both these steps, but I would have to provide my password twice. Is there any way to combine the steps so that I only provide my password once?

为了让我的生活更轻松一点,我想将这两个步骤合二为一。我可以轻松编写一个执行这两个步骤的函数,但我必须提供两次密码。有什么方法可以组合这些步骤,以便我只提供一次密码?

Before somebody suggests it, key-based ssh-logins are not an option. It has been specifically disabled by the Administrators for security reasons.

在有人建议之前,基于密钥的 ssh 登录不是一种选择。出于安全原因,它已被管理员特别禁用。

Solution:

解决方案:

What I ended up doing was a modification of the second solution Wrikken provided. Simply wrapping up his first suggestion in a function would have gotten the job done, but I liked the idea of being able to print multiple documents without having to type my password once per document. I have a rather long password and I'm a lazy typist :)

我最终做的是修改 Wrikken 提供的第二个解决方案。简单地将他的第一个建议包含在一个函数中就可以完成工作,但我喜欢能够打印多个文档而不必为每个文档输入一次密码的想法。我有一个很长的密码,而且我是一个懒惰的打字员 :)

So, what I did was take a sequence of commands and wrap them up in a python script. I used python because I wanted to parameterize the script, and I find it easiest to do in python. I cheated and just ran bash commands from python through os.system. Python just handled parameterization and flow control. The logic was as follows:

所以,我所做的是获取一系列命令并将它们包装在一个 python 脚本中。我使用 python 是因为我想参数化脚本,我发现在 python 中它最容易做。我作弊了,只是通过 os.system 从 python 运行 bash 命令。Python 只是处理参数化和流控制。逻辑如下:

if socket does not exist:
    run bash command to create socket with timeout
copy file using the created socket
ssh command to print using socket

In addition to using a timeout, I also put have an option in my python script to manually close the socket should I wish to do so.

除了使用超时之外,我还在我的 python 脚本中添加了一个选项来手动关闭套接字,如果我愿意的话。

If anyone wants the code, just let me know and I'll either paste-bin it or put it on my git repo.

如果有人想要代码,请告诉我,我要么将其粘贴到垃圾箱中,要么将其放在我的 git 存储库中。

回答by Wrikken

ssh user@host 'cat - > /tmp/file.ext; do_something_with /tmp/file.ext;rm /tmp/file.ext' < file.ext 

Another option would be to just leave an ssh tunnel open:

另一种选择是让 ssh 隧道保持打开状态:

In ~/.ssh/config:

在 ~/.ssh/config 中:

Host *
        ControlMaster auto
        ControlPath ~/.ssh/sockets/ssh-socket-%r-%h-%p

.

.

$ ssh -f -N -l user host
(socket is now open)

Subsequent ssh/scp requests will reuse the already existing tunnel.

后续的 ssh/scp 请求将重用已经存在的隧道。

回答by Alex Che

Here is bash script template, which follows @Wrikken's second method, but can be used as is - no need to edit user's SSH config file:

这是 bash 脚本模板,它遵循@Wrikken 的第二种方法,但可以按原样使用 - 无需编辑用户的 SSH 配置文件:

#!/bin/bash

TARGET_ADDRESS= # the first script argument
HOST_PATH= # the second script argument
TARGET_USER=root
TMP_DIR=$(mktemp -d)
SSH_CFG=$TMP_DIR/ssh-cfg
SSH_SOCKET=$TMP_DIR/ssh-socket
TARGET_PATH=/tmp/file

# Create a temporary SSH config file:
cat > "$SSH_CFG" <<ENDCFG
Host *
        ControlMaster auto
        ControlPath $SSH_SOCKET
ENDCFG

# Open a SSH tunnel:
ssh -F "$SSH_CFG" -f -N -l $TARGET_USER $TARGET_ADDRESS

# Upload the file:
scp -F "$SSH_CFG" "$HOST_PATH" $TARGET_USER@$TARGET_ADDRESS:"$TARGET_PATH"

# Run SSH commands:
ssh -F "$SSH_CFG" $TARGET_USER@$TARGET_ADDRESS -T <<ENDSSH
# Do something with $TARGET_PATH here
ENDSSH

# Close the SSH tunnel:
ssh -F "$SSH_CFG" -S "$SSH_SOCKET" -O exit "$TARGET_ADDRESS"