/** * Start the application * * @throws IOException if there is a problem with connection * @throws InterruptedException if thread was interrupted */ private void start() throws IOException, InterruptedException { Connection c = new Connection(myHost.getHostName(), myHost.getPort()); try { configureKnownHosts(c); c.connect(new HostKeyVerifier()); authenticate(c); final Session s = c.openSession(); try { s.execCommand(myCommand); // Note that stdin is not being waited using semaphore. // Instead, the SSH process waits for remote process exit // if remote process exited, none is interested in stdin // anyway. forward("stdin", s.getStdin(), System.in, false); forward("stdout", System.out, s.getStdout(), true); forward("stderr", System.err, s.getStderr(), true); myForwardCompleted.acquire(2); // wait only for stderr and stdout s.waitForCondition(ChannelCondition.EXIT_STATUS, Long.MAX_VALUE); Integer exitStatus = s.getExitStatus(); if (exitStatus == null) { // broken exit status exitStatus = 1; } System.exit(exitStatus.intValue() == 0 ? myExitCode : exitStatus.intValue()); } finally { s.close(); } } finally { c.close(); } }
private boolean runInitScript( final Computer computer, final PrintStream logger, final Connection conn, final SCPClient scp) throws IOException, InterruptedException { String initScript = Util.fixEmptyAndTrim(computer.getNode().getInitScript()); if (initScript == null) { return true; } if (conn.exec("test -e ~/.hudson-run-init", logger) == 0) { return true; } logger.println("Executing init script"); scp.put(initScript.getBytes("UTF-8"), "init.sh", "/tmp", "0700"); Session session = conn.openSession(); session.requestDumbPTY(); // so that the remote side bundles stdout and stderr session.execCommand(buildUpCommand(computer, "/tmp/init.sh")); session.getStdin().close(); // nothing to write here session.getStderr().close(); // we are not supposed to get anything from stderr IOUtils.copy(session.getStdout(), logger); int exitStatus = waitCompletion(session); if (exitStatus != 0) { logger.println("init script failed: exit code=" + exitStatus); return false; } session.close(); // Needs a tty to run sudo. session = conn.openSession(); session.requestDumbPTY(); // so that the remote side bundles stdout and stderr session.execCommand(buildUpCommand(computer, "touch ~/.hudson-run-init")); session.close(); return true; }
/** * Connects to the given {@link Computer} via SSH and installs Java/Jenkins agent if necessary. */ @Override public void launch(SlaveComputer _computer, TaskListener listener) { Computer computer = (Computer) _computer; PrintStream logger = listener.getLogger(); Date startDate = new Date(); logger.println("Start time: " + getUtcDate(startDate)); final Connection conn; Connection cleanupConn = null; boolean successful = false; try { conn = connectToSsh(computer, logger); cleanupConn = conn; logger.println("Authenticating as " + computer.getRemoteAdmin()); if (!conn.authenticateWithPublicKey( computer.getRemoteAdmin(), computer.getNode().getPrivateKey().toCharArray(), "")) { logger.println("Authentication failed"); throw new Exception("Authentication failed"); } final SCPClient scp = conn.createSCPClient(); if (!runInitScript(computer, logger, conn, scp)) { return; } if (!installJava(logger, conn)) { return; } logger.println("Copying slave.jar"); scp.put(Jenkins.getInstance().getJnlpJars("slave.jar").readFully(), "slave.jar", "/tmp"); String jvmOpts = Util.fixNull(computer.getNode().getJvmOpts()); String launchString = "java " + jvmOpts + " -jar /tmp/slave.jar"; logger.println("Launching slave agent: " + launchString); final Session sess = conn.openSession(); sess.execCommand(launchString); computer.setChannel( sess.getStdout(), sess.getStdin(), logger, new Channel.Listener() { @Override public void onClosed(Channel channel, IOException cause) { sess.close(); conn.close(); } }); successful = true; } catch (Exception e) { LOGGER.log(Level.WARNING, e.getMessage(), e); try { Jenkins.getInstance().removeNode(computer.getNode()); } catch (Exception ee) { ee.printStackTrace(logger); } e.printStackTrace(logger); } finally { Date endDate = new Date(); logger.println("Done setting up at: " + getUtcDate(endDate)); logger.println( "Done in " + TimeUnit2.MILLISECONDS.toSeconds(endDate.getTime() - startDate.getTime()) + " seconds"); if (cleanupConn != null && !successful) { cleanupConn.close(); } } }