Open westonruter opened 10 years ago
A promising start. Even just caching the vagrant-ssh-config
output causes a great speedup.
wp_cli_ssh_id=example.com; if [ ! -e /tmp/vagrant-ssh-config-$wp_cli_ssh_id ]; then vagrant ssh-config > /tmp/vagrant-ssh-config-$wp_cli_ssh_id; echo -e "ControlMaster auto\nControlPath /tmp/vagrant-ssh-controlpath-$wp_cli_ssh_id" >> /tmp/vagrant-ssh-config-$wp_cli_ssh_id; fi && if [ ! -e /tmp/vagrant-ssh-controlpath-$wp_cli_ssh_id ]; then ssh -q -F /tmp/vagrant_ssh_config default; fi; ssh -q %pseudotty% -F /tmp/vagrant_ssh_config default %cmd%
It should be backgrounding the ssh
command inside of the conditional, however, but &
seems to be illegal inside of an if
statement.
I would like to see a speedup of the connection as well. I found a gist which looks related to this: https://gist.github.com/jedi4ever/5657094
When using ControlMaster, it looks like there isn't a need to cache the ssh-confg. Here's a script I came up with that is working okay. Does this help at all in your case, or do you find other caching and/or DNS tricks are also needed?
#!/bin/bash
# fastssh.sh
hostname=default
function fastssh() {
if [ ! -e .vagrant-ssh ]; then
vagrant ssh-config $hostname | ssh -t -t -F/dev/stdin -o 'ControlMaster auto' -o 'ControlPath .vagrant-ssh' -f -N $hostname
fi
ssh -o 'ControlMaster auto' -o 'ControlPath .vagrant-ssh' $hostname "$@"
}
fastssh "$@"
@dhbaird thanks for that. What happens when the SSH connection gets cut? The .vagrant-ssh
file will persist, but it won't work anymore right?
@westonruter yeah, you've got a good point there. If the ControlMaster gets killed, then it appears to leave a stale .vagrant-ssh
, and the first attempt to connect will yield this message and remove .vagrant-ssh
:
ssh: Could not resolve hostname default: Name or service not known
The second attempt to connect, because .vagrant-ssh
is removed will succeed. So, here's a new script that retries exactly once. But I'm not sure what to do about it printing the extraneous "Could not resolve hostname..." message:
#!/bin/bash
# fastssh.sh
hostname=default
function fastssh() {
if [[ ! -S .vagrant-ssh ]]; then
vagrant ssh-config $hostname | ssh -t -t -F/dev/stdin -o 'ControlMaster auto' -o 'ControlPath .vagrant-ssh' -f -N $hostname
fi
ssh -o 'ControlMaster auto' -o 'ControlPath .vagrant-ssh' $hostname "$@"
# if the attempt failed, retry exactly once:
if [[ $? != 0 && ! -S .vagrant-ssh ]]; then
vagrant ssh-config $hostname | ssh -t -t -F/dev/stdin -o 'ControlMaster auto' -o 'ControlPath .vagrant-ssh' -f -N $hostname
ssh -o 'ControlMaster auto' -o 'ControlPath .vagrant-ssh' $hostname "$@"
fi
}
fastssh "$@"
Could the PID for that initial connection be captured somehow? Then you could check to see if the PID is still valid in addition to whether the .vagrant-ssh
is present.
Sorry for such a long wait, but here is a script that seems to be working very well. It automatically re-initializes the control channel if SSH got killed, and then maintains a backgrounded ssh for up to 120 minutes. It also gives you proper stdio and return code, just like normal ssh should:
fastssh() {
[[ -e .vagrant_ssh_config ]] || vagrant ssh-config >.vagrant_ssh_config </dev/null
ssh -F .vagrant_ssh_config \
-o 'ControlMaster auto' \
-o 'ControlPath .vagrant_ssh_control' \
-o 'ControlPersist 120m' default "$@"
return $?
}
...I think it still needs an detection to figure out when the ssh-config has gone stale, and needs to re-run vagrant ssh-config
...
Looking good!
Could there be an incremental improvement opportunity here, based on let's say documentation on just how to use ~/.ssh/config
to set ControlMaster
in a global fashion? It looks like the above stuff tries to address "works for everybody everywhere" and it doesn't seem to be easy, based on the timeline here.
My motivation is getting wp ssh
bash-completion as discussed in #21. Even though you could bash-complete also based on local installation and just live with possible configuration difference errors. But either way, just having multiple commands run quicker is a great win too.
So this totally works, put it in your ~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
Now mkdir ~/.ssh/sockets
so it has a place to store the... well, sockets.
wp ssh
runs very fast now. If the connection is anything half decent, should be quite usable for even remote bash-completion.
There is a configuration for SSH called ControlPath which keeps a single connection open across multiple SSH sessions, meaning subsequent connections re-use the initial connection and thus connect very fast. It would be great to make WP-CLI SSH use this somehow, where the initial SSH connection is not killed.