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
How can I scp a file and run an ssh command asking for password only once?
提问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"

