Install Jenkins agent as a Windows service in command line
Asked Answered
P

4

15

I have been looking a lot on Google on how to install the service in command line (so without manual interaction) but I am stuck on how to get the jenkins-slave.exe

I found those instruction https://wiki.jenkins.io/display/JENKINS/Installing+Jenkins+as+a+Windows+service but I can't figure how to get the executable. I have downloaded and run the slave.jar with the right key, which connects the agent, but the exe is not generated.

I found this page https://github.com/kohsuke/winsw/blob/master/doc/installation.md#winsw-installation-guide to install it manually but that sounds like re-invented the wheel when the jar can do it. Plus there is a risk the WinSW.exe is different and doesn't get updated by the plugin (I saw some automatic update code in it).

So is there a way I can download the jenkins-slave.exe or generate it? or is there a way to run the "Install as a service" in command line from the slave.jar?

Platelet answered 26/6, 2017 at 1:5 Comment(1)
P
22

To answer my own question, after having contacted the plugin developers:

There is no actual way to download the exe from Jenkins directly, the slave.jar gets it from the master via the remoting protocol. I have created a request to be able to download it via an URL (as suggested by the developer), so it might be available in the future.

Right now the executable is a renamed Windows Service Wrapper binary: https://github.com/kohsuke/winsw so I used this binary the same way.

Regarding the configuration used by WinSW and XML files, I used the one from the GitHub repository https://github.com/jenkinsci/windows-slave-installer-module. The versions are compatible in terms of the configuration.

So basically I download the exe, get the private key from Jenkins and create the service using the configuration from the original plugin. Then I install the service using jenkins-slave.exe install.

Step by step:

  • Get the JNLP command from Jenkins (from the Node page) to get the private key, e.g. java -jar slave.jar -jnlpUrl http://jenkins...
  • Download the slave.jar file from Jenkins (gotten from the JNLP command)
  • Download the service wrapper executable, e.g. http://repo.jenkins-ci.org/public/com/sun/winsw/winsw/2.1.0/winsw-2.1.0-bin.exe
  • Rename winsw-2.1.0-bin.exe into jenkins-slave.exe
  • Setup the XML used to run the service (available in the module or directly on winsw website)
  • Setup the slave configuration XML file (available on the module source code)
  • Then install the service using jenkins-slave.exe install
Platelet answered 10/8, 2017 at 1:54 Comment(4)
Do you have any step-by-step instructions for this please? I'm not understanding the high-level outline.Duchess
@Duchess I have added step by step instructions.Platelet
Thanks, is it necessary to rename winsw-2.1.0-bin.exe to jenkins-slave.exe?Duchess
No it's not, that's just how they do it in Jenkins.Platelet
T
5

What I would do is:

  • Download the slave.jar file (from the node's page of Jenkins)
  • Copy the java -jar slave.jar -jnlpUrl http://<YOUR URL HERE> command from the node's page
  • Paste this command into a new .bat file and save it
  • Register a scheduled task to run this .bat file when Windows starts
Tragedian answered 5/10, 2018 at 7:22 Comment(4)
@alex I believe so, I am using a build server which I get to run as a slave using this .bat file I created.Tragedian
If you do this, make sure your paths to the jar file are absolute in the script so that it can work on startup instead of logging in, ie don't rely on environment variables. It probably doesn't need to be that way, but I've had issues in the past when not using abso-paths and doing this kind of jenkins scheduled start behavior.Catafalque
@Tragedian i have done this but in the Jenkins UI i cannot see logs it loads forever, and if I add the java command any >> to redirect output it doesn't work, any ideas?Trioxide
@BatchenRegev I'm not sure sorry, I haven't looked at it for a long time.Tragedian
F
2

Or is there a way to run the "Install as a service" in command line from the slave.jar?

I don't use jenkins-slave.exe, but instead a custom script in which I can control the exact environment variable I want to set for the Jenkins slave, when launching java -jar slave.jar with the secret key you can see in the Jenkins master node page for that new slave.

To get slave.jar from the master onto the slave, execute from the slave Windows server:

curl -o slave.jar https://your.server/jenkins/jnlpJars/slave.jar

To replace the jenkins-slave.exe, I use a script declared as a Windows service, with nssm

The script is similar to agent.bat:

set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0
set PATH=D:\Tools\SonarRunner\bin;%PATH%
set M2_HOME=D:\Tools\apache-maven-3.5.0
set PATH=%M2_HOME%\bin;%PATH%
set PATH=D:\Tools\apache-ant-1.9.3\bin;%PATH%
set GH=D:\Tools\Git
set PATH=%GH%\bin;%GH%\usr\bin;%GH%\mingw64\bin;%PATH%
set PATH=%JAVA_HOME%\bin;%PATH%

set WORKSPACE_FOLDER=D:\Jenkins\workspace
set GIT_WORKSPACE_FOLDER=D:\Jenkins\workspace

java -Xmx768m -jar slave.jar -jnlpUrl https://your.server/jenkins/computer/<SlaveName>/slave-agent.jnlp -secret 87ef3d...

That script is then called as a Windows service, ran by a dedicated user account:

runas /user:<domain>\<jenkinsUser> cmd ( enter `jenkinsUser` Windows password )

D:\Tools\nssm-2.24\win64\nssm.exe install <SlaveName> D:\Jenkins\agent.bat

Its Windows service is then configured:

sc config <SlaveName> obj= <domain>\<jenkinsUsers> password= <jenkinsUser password>
sc config <SlaveName> start= auto

For automating the installation of other software: see Chocolatey - Software Management Automation, The package manager for Windows.


To fully automate the declaration-side of slaves, use the web API to create the slave, and a groovy script to retrieve the Jenkins node/slave secret JnlpMac key.
See this script for the creation.
And the groovy script (with Jenkins 2.46 or newer) to get the secret key:

echo 'println jenkins.model.Jenkins.instance.nodesObject.getNode("my-agent")?.computer?.jnlpMac' \
  | java -jar ~/Downloads/jenkins-cli.jar -s https://jenkins/ groovy =
Fullscale answered 26/6, 2017 at 4:52 Comment(2)
Thank you but that's similar to what they describe in the documentation using WinSW that is to create a service manually. I would prefer it to be automatic.Platelet
@MaximeViargues That is why I put "To fully automate the declaration-side of slaves"Fullscale
T
0

Using this windows service wrapper works too: https://github.com/winsw/winsw

follow their installation, but you should update the xml with your desired configuration, be sure to remove all " in pathes within the xml and disable websockets in the jenkins master configuration page of the agent:

disbale websocket agent config option

step by step: download the exe: WinSW-x64.exe from https://github.com/winsw/winsw/releases create your workspace-dir on the agent and paste it there, rename the WinSW-x64.exe to jenkins-slave.exe

copy your jenkins-slave.xml there, it should looke like:

<service>
  <id>jenkins</id>
  <name>Jenkins</name>
  <description>This service runs Jenkins continuous integration system.</description>
  <env name="JENKINS_HOME" value="%BASE%"/>
  <executable>C:\Program Files\RedHat\java-1.8.0-openjdk-1.8.0.275-1\jre\bin\java.exe</executable>
  <arguments>-jar %BASE%\slave.jar -jnlpUrl https://<your_jenkins>.jenkins.bshg.com/computer/RBGWCW0281/jenkins-agent.jnlp -secret <your_secret> -workDir C:\<workspace-dir>\ -noCertificateCheck</arguments>
  <logmode>rotate</logmode>

  <onfailure action="restart" />
  <delayedAutoStart/>
  
  <!--
    If uncommented, download the Remoting version provided by the Jenkins master.
    Enabling for HTTP implies security risks (e.g. replacement of JAR via DNS poisoning). Use on your own risk.
    NOTE: This option may fail to work correctly (e.g. if Jenkins is located behind HTTPS with untrusted certificate).
    In such case the old agent version will be used; you can replace slave.jar manually or to specify another download URL.
  -->
  <download from="https://<your_jenkins>.jenkins.bshg.com/jnlpJars/slave.jar" to="%BASE%\slave.jar"/>
  
  <!-- 
    In the case WinSW gets terminated and leaks the process, we want to abort
    these runaway JAR processes on startup to prevent "Slave is already connected errors" (JENKINS-28492).
  -->
  <extensions>
    <!-- This is a sample configuration for the RunawayProcessKiller extension. -->
    <extension enabled="true" 
               className="winsw.Plugins.RunawayProcessKiller.RunawayProcessKillerExtension"
               id="killOnStartup">
      <pidfile>%BASE%\jenkins_agent.pid</pidfile>
      <stopTimeout>5000</stopTimeout>
      <stopParentFirst>false</stopParentFirst>
    </extension>
  </extensions>
</service>

Use the option delayed Auto start, to ensure all the network services are started, that jenkins connect can not fail. And i recommend to use a registry key to give the service more time to start: Insert registry-key to give services more time to start:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\]
"ServicesPipeTimeout"=dword:0001d4c0

You can check here fore detailed info: https://serverfault.com/questions/622432/how-do-i-increase-windows-service-startup-timeout

And finally I recommend to autostart your jenkins at least once a week. with a scheduled task:

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2020-04-30T12:47:51.8471206</Date>
    <Author>Domain/User</Author>
    <Description>Some Comment</Description>
    <URI>\CI-Restart</URI>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2020-05-01T01:00:00</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>whatever</UserId>
      <LogonType>Password</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>shutdown</Command>
      <Arguments>/r /f /t 10 /d p:2:3 /c "CI-reconnect"</Arguments>
    </Exec>
  </Actions>
</Task>

Now do (with admin rights)

  • jenkins-slave.exe install
  • jenkins-slave.exe start

Your Jenkins will run forever!

Another recommendation: Enable the BIOS-setting to start pc on power-on. If you have troubles with interruptions of power-supply.

Trellas answered 15/2, 2022 at 19:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.