aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/ssh.cc23
-rw-r--r--src/libstore/ssh.hh1
-rw-r--r--tests/nixos/nix-copy.nix10
3 files changed, 27 insertions, 7 deletions
diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc
index 6f6deda51..fae99d75b 100644
--- a/src/libstore/ssh.cc
+++ b/src/libstore/ssh.cc
@@ -41,6 +41,11 @@ void SSHMaster::addCommonSSHOpts(Strings & args)
args.push_back("-oLocalCommand=echo started");
}
+bool SSHMaster::isMasterRunning() {
+ auto res = runProgram(RunOptions {.program = "ssh", .args = {"-O", "check", host}, .mergeStderrToStdout = true});
+ return res.first == 0;
+}
+
std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string & command)
{
Path socketPath = startMaster();
@@ -97,7 +102,7 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string
// Wait for the SSH connection to be established,
// So that we don't overwrite the password prompt with our progress bar.
- if (!fakeSSH && !useMaster) {
+ if (!fakeSSH && !useMaster && !isMasterRunning()) {
std::string reply;
try {
reply = readLine(out.readSide.get());
@@ -133,6 +138,8 @@ Path SSHMaster::startMaster()
logger->pause();
Finally cleanup = [&]() { logger->resume(); };
+ bool wasMasterRunning = isMasterRunning();
+
state->sshMaster = startProcess([&]() {
restoreProcessContext();
@@ -152,13 +159,15 @@ Path SSHMaster::startMaster()
out.writeSide = -1;
- std::string reply;
- try {
- reply = readLine(out.readSide.get());
- } catch (EndOfFile & e) { }
+ if (!wasMasterRunning) {
+ std::string reply;
+ try {
+ reply = readLine(out.readSide.get());
+ } catch (EndOfFile & e) { }
- if (reply != "started")
- throw Error("failed to start SSH master connection to '%s'", host);
+ if (reply != "started")
+ throw Error("failed to start SSH master connection to '%s'", host);
+ }
return state->socketPath;
}
diff --git a/src/libstore/ssh.hh b/src/libstore/ssh.hh
index c86a8a986..94b952af9 100644
--- a/src/libstore/ssh.hh
+++ b/src/libstore/ssh.hh
@@ -28,6 +28,7 @@ private:
Sync<State> state_;
void addCommonSSHOpts(Strings & args);
+ bool isMasterRunning();
public:
diff --git a/tests/nixos/nix-copy.nix b/tests/nixos/nix-copy.nix
index ee8b77100..16c477bf9 100644
--- a/tests/nixos/nix-copy.nix
+++ b/tests/nixos/nix-copy.nix
@@ -23,6 +23,12 @@ in {
nix.settings.substituters = lib.mkForce [ ];
nix.settings.experimental-features = [ "nix-command" ];
services.getty.autologinUser = "root";
+ programs.ssh.extraConfig = ''
+ Host *
+ ControlMaster auto
+ ControlPath ~/.ssh/master-%h:%r@%n:%p
+ ControlPersist 15m
+ '';
};
server =
@@ -62,6 +68,10 @@ in {
client.wait_for_text("done")
server.succeed("nix-store --check-validity ${pkgA}")
+ # Check that ControlMaster is working
+ client.send_chars("nix copy --to ssh://server ${pkgA} >&2; echo done\n")
+ client.wait_for_text("done")
+
client.copy_from_host("key", "/root/.ssh/id_ed25519")
client.succeed("chmod 600 /root/.ssh/id_ed25519")