# Invocation of 'sh' on Windows should provide a more helpful error

#### Details

• Type: Improvement
• Status: Open
• Priority: Minor
• Resolution: Unresolved
• Component/s:
• Labels:
• Similar Issues:

#### Description

Right now if your pipeline script inadvertently tries to invoke the sh step, something approximating this error will fail your build:

```java.io.IOException: Cannot run program "nohup" (in directory "C:\Program Files (x86)\Jenkins\workspace\fathertime"): CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(Unknown Source)
at hudson.Proc\$LocalProc.<init>(Proc.java:244)
at hudson.Proc\$LocalProc.<init>(Proc.java:216)
at hudson.Launcher\$LocalLauncher.launch(Launcher.java:815)
at hudson.Launcher\$ProcStarter.start(Launcher.java:381)
at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:136)
at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:113)
at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1277)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1171)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:812)
at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:46)
at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1277)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1171)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:15)
at WorkflowScript.run(WorkflowScript:11)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:55)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock\$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:106)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock\$ContinuationImpl.fixArg(FunctionCallBlock.java:79)
at sun.reflect.GeneratedMethodAccessor174.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
at com.cloudbees.groovy.cps.Next.step(Next.java:58)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:154)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService\$2.call(CpsVmExecutorService.java:47)
at hudson.remoting.SingleLaneExecutorService\$1.run(SingleLaneExecutorService.java:112)
at jenkins.util.ContextResettingExecutorService\$1.run(ContextResettingExecutorService.java:28)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
at java.lang.ProcessBuilder.start(Unknown Source)
at hudson.Proc\$LocalProc.<init>(Proc.java:244)
at hudson.Proc\$LocalProc.<init>(Proc.java:216)
at hudson.Launcher\$LocalLauncher.launch(Launcher.java:815)
at hudson.Launcher\$ProcStarter.start(Launcher.java:381)
at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:136)
at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:113)
at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1277)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1171)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:812)
at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:46)
at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1277)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1171)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:15)
... 24 more
Finished: FAILURE
```

I expect the build to error out, but something more helpful would be nice, like "The `sh` step is not supported on the Windows platform, please use `bat` or install Cygwin"

#### Activity

Hide
Toshitaka Tandai added a comment -

I Resolved this by arranging peschmae peschmae 's code above.try it

```mklink "C:\Program Files\Git\cmd\nohup.exe" "C:\Program Files\git\usr\bin\nohup.exe"

```
Show
Toshitaka Tandai added a comment - I Resolved this by arranging peschmae peschmae 's code above.try it mklink "C:\Program Files\Git\cmd\nohup.exe" "C:\Program Files\git\usr\bin\nohup.exe" mklink "C:\Program Files\Git\cmd\msys-2.0.dll" "C:\Program Files\git\usr\bin\msys-2.0.dll" mklink "C:\Program Files\Git\cmd\msys-iconv-2.dll" "C:\Program Files\git\usr\bin\msys-iconv-2.dll" mklink "C:\Program Files\Git\cmd\msys-intl-8.dll" "C:\Program Files\git\usr\bin\msys-intl-8.dll" but I met https://issues.jenkins-ci.org/browse/JENKINS-38211 ...
Hide
Nick Jones added a comment - - edited

With Git for Windows 2.16.2, I was able to add C:\Program Files\Git\usr\bin to the PATH (rather than C:\Program Files\Git\bin) and consequently my sh commands work in both FreeStyle and Pipeline builds. No mklink was necessary.

Show
Nick Jones added a comment - - edited With Git for Windows 2.16.2, I was able to add C:\Program Files\Git\usr\bin to the PATH (rather than C:\Program Files\Git\bin) and consequently my sh commands work in both FreeStyle and Pipeline builds. No mklink was necessary.
Hide
Antony Gelberg added a comment - - edited

Happening here as well with Git Bash, sadly the workarounds didn't work for me at all even when I altered PATH:

```pipeline {
environment {
PATH = "C:\\Program Files\\Git\\usr\\bin;C:\\Program Files\\Git\\bin;\${env.PATH}"
stages {
stage('Sanity check') {
steps {
sh 'script/code_scan.sh'
}
}
...
```

I did bat 'sh -c script/code_scan.sh' instead ,which seems to work but is ugly and might hide gremlins.

Errors were of the form:

```java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
Also:   hudson.remoting.Channel\$CallSiteStackTrace: Remote call to windows-server-2012 (i-09233a1df87ee74c0)
at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1737)
at hudson.remoting.UserResponse.retrieve(UserRequest.java:313)
at hudson.remoting.Channel.call(Channel.java:952)
at hudson.Launcher\$RemoteLauncher.launch(Launcher.java:1052)
at hudson.Launcher\$ProcStarter.start(Launcher.java:449)
at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:229)
at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:153)
at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:108)
at sun.reflect.GeneratedMethodAccessor6254.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.kohsuke.groovy.sandbox.impl.Checker\$1.call(Checker.java:157)
at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:133)
at org.kohsuke.groovy.sandbox.impl.Checker\$1.call(Checker.java:155)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:129)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock\$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock\$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
at sun.reflect.GeneratedMethodAccessor198.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
at com.cloudbees.groovy.cps.Next.step(Next.java:83)
at com.cloudbees.groovy.cps.Continuable\$1.call(Continuable.java:174)
at com.cloudbees.groovy.cps.Continuable\$1.call(Continuable.java:163)
at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access\$101(SandboxContinuable.java:34)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda\$run0\$0(SandboxContinuable.java:59)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService\$2.call(CpsVmExecutorService.java:64)
at hudson.remoting.SingleLaneExecutorService\$1.run(SingleLaneExecutorService.java:131)
at jenkins.util.ContextResettingExecutorService\$1.run(ContextResettingExecutorService.java:28)
Caused: java.io.IOException: Cannot run program "nohup" (in directory "c:\jenkins\workspace\web"): CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(Unknown Source)
at hudson.Proc\$LocalProc.<init>(Proc.java:249)
at hudson.Proc\$LocalProc.<init>(Proc.java:218)
at hudson.Launcher\$LocalLauncher.launch(Launcher.java:929)
at hudson.Launcher\$ProcStarter.start(Launcher.java:449)
at hudson.Launcher\$RemoteLaunchCallable.call(Launcher.java:1299)
at hudson.Launcher\$RemoteLaunchCallable.call(Launcher.java:1259)
at hudson.remoting.UserRequest.perform(UserRequest.java:210)
at hudson.remoting.UserRequest.perform(UserRequest.java:53)
at hudson.remoting.Request\$2.run(Request.java:364)
at hudson.remoting.InterceptingExecutorService\$1.call(InterceptingExecutorService.java:72)
```
Show
Hide
Carel Combrink added a comment -

I had to set the PATH System variable on the computer before I could get sh to work on Windows.

Setting it in the  "List of variables" on the configuration page of the node in Jenkins allowed me to use the workaround as mentioned by Antony Gelberg
Only once I set it in Windows and restarted the node could I use the "sh" command directly from within my script.

Show
Carel Combrink added a comment - I had to set the PATH System variable on the computer before I could get sh  to work on Windows. Setting it in the  "List of variables" on the configuration page of the node in Jenkins allowed me to use the workaround as mentioned by Antony Gelberg Only once I set it in Windows and restarted the node could I use the "sh" command directly from within my script.
Hide
ethorsa added a comment - - edited

I had to set the PATH System variable on the computer before I could get sh to work on Windows.

That's important, it doesn't work otherwise. Adding it to PATH from within the pipeline (eg. withEnv(...) or environment { ... }) doesn't work.

Show
ethorsa added a comment - - edited I had to set the PATH System variable on the computer before I could get  sh  to work on Windows. That's important, it doesn't work otherwise. Adding it to PATH from within the pipeline (eg. withEnv(...)  or environment { ... }) doesn't work.

#### People

• Assignee:
Jesse Glick
Reporter:
R. Tyler Croy