简体   繁体   中英

'mvn' command not recognized on Jenkins Windows slave node

I'm trying to build a Java project on a Jenkins Windows slave node, and when I try to run any mvn command on the slave from the Jenkins service, I get an error saying the command cannot be found:

java.io.IOException: Cannot run program "mvn": CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at java.lang.Runtime.exec(Runtime.java:620)
...

NOTE: If I log into the machine directly, running any mvn command works just fine.

Windows Slave Node Setup

Maven is installed to the directory D:\\Apache\\Maven .

Set system environment variables:

  • JAVA_HOME = C:\\Program Files\\Java\\jdk1.8.0_40
  • M2 = %M2_HOME%\\bin
  • M2_HOME = D:\\Apache\\Maven

The PATH system environment variable is set to %M2%;...

From the Jenkins master's webpage, if I run the Groovy script println System.getenv("PATH") on the Windows slave node, I can see that is has the correct, expanded path for Maven's bin directory.

I can also verify Maven's bin directory can be seen by running the following:

Groovy Script: println "ls -al D:/Apache/Maven/bin".execute().text

 total 14 drwxr-xr-x 8 D-AUN-00 Administ 4096 Apr 20 12:35 . drwxr-xr-x 9 D-AUN-00 Administ 4096 Mar 31 11:46 .. -rw-r--r-- 1 D-AUN-00 Administ 230 Mar 31 11:46 m2.conf -rwxr-xr-x 1 D-AUN-00 Administ 7085 Apr 20 11:49 mvn -rw-r--r-- 1 D-AUN-00 Administ 6007 Mar 31 11:46 mvn.cmd -rwxr-xr-x 1 D-AUN-00 Administ 1796 Mar 31 11:46 mvnDebug -rw-r--r-- 1 D-AUN-00 Administ 1513 Mar 31 11:46 mvnDebug.cmd -rwxr-xr-x 1 D-AUN-00 Administ 1843 Mar 31 11:46 mvnyjp 

Curiously, if I run Maven with mvn.cmd , then Maven runs just fine:

Groovy Script: println "mvn.cmd --version".execute().text

 Apache Maven 3.3.1 (cab6659f9874fa96462afef40fcf6bc033d58c1c; 2015-03-13T15:10:27-05:00) Maven home: D:\\Apache\\Maven Java version: 1.8.0_40, vendor: Oracle Corporation Java home: C:\\Program Files\\Java\\jdk1.8.0_40\\jre Default locale: en_US, platform encoding: Cp1252 OS name: "windows 8.1", version: "6.3", arch: "amd64", family: "dos" 

Question: Is there something I'm missing or haven't setup properly that would cause the mvn command to not be recognized?


EDIT: The build I'm running uses a custom Python bash script to invoke Maven. The script is also setup to run builds for projects in other languages (PHP, Ruby, .NET, Node) and the tools for those builds all work just fine ( composer , bundle , devenv.com ). However, I would think that how the build is performed shouldn't matter if the script console for the slave node returns the same error when attempting to run mvn commands.


EDIT 2: The more I look into this, the less I feel this has anything to do with Jenkins and more to do with how shell scripts are executed on Windows. When I use the Script Console to invoke a Groovy Script on the slave node, Jenkins simply writes that out to a temporary file on the slave node and uses sh -xe <script> to invoke it. When I try a similar approach directly on the Windows machine, every script-based command (eg mvn , composer ) fails to run from within a shell script unless I prepend the command with sh . This is unfortunate because the scripts I'm running may be run on a Linux or Mac node in the future, and I'd rather not litter it with Windows-specific commands. I've tried this with both Git Bash and Msysgit, and I get the same results. Next, I'll be trying Cygwin to see if that works...

The maven installation folder should be the same on both Jenkins master and client. Check if the folder location is same on both master and slave.

Other than that your env. properties are correct but check if you have added the properties under user or system properties. If you have added the properties under user and are starting the Jenkins slave as a windows service I don't think Jenkins picks up the values.

So it turns out that this is related to how shell commands are invoked on Windows in context of different tools.

Jenkins Script Console & Groovy

In Jenkins, when using a Windows node's Script Console , the Groovy script will invoke scripted commands as though they are Win32 application or BATCH script calls (eg "mvn --version".execute() will not work because mvn is a shell script - "mvn.cmd --version".execute() will work because mvn.cmd is a BATCH script).

When running Groovy script commands on a Windows node, commands that use shell scripts will need to be prepended with sh in order to be explicit. This assumes your Windows node has a path to a shell executable in its PATH system environment variable.

Sample Groovy script that works when invoked on a Windows node:

println "sh mvn --version".execute().text

Python on Windows

I also realized that my Python build script suffers from a somewhat similar issue. If you try and run a Python script on Windows that calls a shell script via subprocess , it won't work unless you include shell=True in the call. Alternatively, you can prepend sh to the command to explicitly invoke a shell

NOTE: This won't work for some tools like bundle for Ruby - for those commands, using shell=True only seemed to work.

Sample Python script that works when invoked in a shell environment on Windows:

#!/usr/bin/env python
import subprocess
subprocess.call("mvn --version", shell=True)

I solve this problem add "#!/usr/bin/env zsh --login" in Execute Shell window Title. It's very easy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM