bash: no job control in this shell

Thanks for the additional commit. I think this looks pretty good. Sorry if I seemed a little reticent to make this change-- this “run” stuff has been changed over and over and I can’t count the number of times I thought I finally thought I had it nailed down only to discover a new use case I hadn’t accounted for,. As such, I try to be careful when touching this code.

I just released 4.1.0 which fixes a couple small bugs in 4.0.0 so I’ll merge this in now and we can let people test it as part of the 4.2.0 cycle.

Hi Brad,
I have one other question regarding something you said earlier in this thread:

So what this means is that you basically can’t pipe or redirect the output of a failing command anywhere as CommandBox has been designed to just abort right there, print the error message and return to the shell. Makes sense now that I think about it.

We have an interceptor for preServerStart that adds an interface alias to the loopback adapter if you’re on a mac and the alias doesn’t already exist. (MacOs only binds 127.0.0.1 to your loopback address instead of the whole 127.0.0.x subnet like every other OS. arrrrrg!) . To detect if the alias exists, I would ping the IP address and pipe that to /dev/null and then check the exit code. If it fails, it fails silently and I know the alias needs to be added.

With commandBox 4.0.0, it sounds like this type of thing is no longer possible. When my interceptor fires and the ping command fails, it prints the stack trace to the screen, “lucee.runtime.exp.CustomTypeException: No active job”. I think this is due to the “throw()” on line 365 of interactiveJob.cfc: “throw( ‘No active job’ );”

My question is, is it no longer possible to execute an external command that fails inside of a *server interceptor? Will the improvement in commandbox 4.1 allow me to execute a command that fails? (Add setting to force “non interactive” shell that disables fancypants progress output)

thanks!
–Joel

We have an interceptor for preServerStart that adds an interface alias to the loopback adapter

Are you using this module, because it does the same thing. https://forgebox.io/view/commandbox-hostupdater

With commandBox 4.0.0, it sounds like this type of thing is no longer possible

Why do you say that? So far as I know, nothing has changed in that regard. Not saying it hasn’t, but I don’t think I changed it intentionally.

it prints the stack trace to the screen, “lucee.runtime.exp.CustomTypeException: No active job”.

That just sounds like a bug! Please report the full stack trace so I can see what code is trying to use an interactive job when there isn’t an active one.

My question is, is it no longer possible to execute an external command that fails inside of a *server interceptor?

Not that I know of, but maybe I’m confused. What is causing this question?

Will the improvement in commandbox 4.1 allow me to execute a command that fails?

I’m confused-- of course you can execute a command that fails. Has that ever not been the case? If you execute a native binary that fails with an exit code of 123, then the “run” command should also fail with the exit code of 123.

(Add setting to force “non interactive” shell that disables fancypants progress output)

No, I wouldn’t expect that to have any effect. Again, a lot of things changed in 4.0 but so far as I know I didn’t change anything in regard to now native binaries fail. Are you seeing a difference?? The only thing I can think of is that you used to not be able to capture the output at all, but now you can.

Brad,
I’m sorry. I did some more testing and discovered a few things. I will remind you that this is, again, on my Mac (high sierra).

  1. As far as I can tell, the ping command seems to be the only command showing this behavior. I wasn’t able to reproduce it with other commands.

  2. The command has to be wrapped in a try/catch. (I didn’t realize this yesterday when I asked about this. Sorry.)

  3. When the above are true and you run the following command (first, make sure 127.0.0.10 isn’t a reachable address, otherwise ping is successful. Use a different IP if necessary) , you will get the stack trace I’ll include at the end of my reply. (I’m using the commandService’s "runCommandLine() method in my interceptor) :

    `
    command.runCommandLine(‘echo “ping -t 2 127.0.0.10 >/dev/null” | run’, true)

    `

  4. I was able to work around this problem with the following command, although I’m not exactly sure why it works:

    command.runCommandLine('echo "ping -t 2 127.0.0.10 >/dev/null; echo $?" | run', true);

I’m guessing it has something to do with the way ping prints the echo replies to the console because it didn’t happen with other failing commands. Is it worth filing a bug report for? Since I found a work-around, I’m happy.

Are you using this module, because it does the same thing. https://forgebox.io/view/commandbox-hostupdater

We used that when it was first released but it didn’t have mac support at the time and, if memory serves, it required that you run ‘box.exe’ with elevated permissions and/or as root. I haven’t been watching that project so I’m not sure if they resolved those issues.

And finally, the stack trace:

CommandBox:myv2> server start

✘ | Starting Server

Command returned failing exit code [2]

ERROR (4.0.0+01015)

No active job

/Users/joel.clegg/.CommandBox/cfml/system/util/InteractiveJob.cfc: line 365

363: var pointer = getJobs();

364: if( !pointer.len() ) {

365: throw( ‘No active job’ );

366: }

367: // Declare a closure here for easy recursion

called from /Users/joel.clegg/.CommandBox/cfml/system/util/InteractiveJob.cfc: line 80

called from /Users/joel.clegg/.CommandBox/cfml/system/util/InteractiveJob.cfc: line 105

called from /Users/joel.clegg/.CommandBox/cfml/system/services/ServerEngineService.cfc: line 161

called from /Users/joel.clegg/.CommandBox/cfml/system/services/ServerEngineService.cfc: line 57

called from /Users/joel.clegg/.CommandBox/cfml/system/services/ServerEngineService.cfc: line 38

called from /Users/joel.clegg/.CommandBox/cfml/system/services/ServerService.cfc: line 750

called from /Users/joel.clegg/.CommandBox/cfml/system/modules_app/server-commands/commands/server/start.cfc: line 150

called from /Users/joel.clegg/.CommandBox/cfml/system/services/CommandService.cfc: line 337

called from /Users/joel.clegg/.CommandBox/cfml/system/services/CommandService.cfc: line 138

called from /Users/joel.clegg/.CommandBox/cfml/system/Shell.cfc: line 747

called from /Users/joel.clegg/.CommandBox/cfml/system/Shell.cfc: line 570

called from /Users/joel.clegg/.CommandBox/cfml/system/Bootstrap.cfm: line 160

lucee.runtime.exp.CustomTypeException: No active job

at lucee.runtime.tag.Throw._doStartTag(Throw.java:212)

at lucee.runtime.tag.Throw.doStartTag(Throw.java:201)

at throw_cfm$cf.udfCall(/throw.cfm:11)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)

at lucee.runtime.functions.system.CFFunction.call(CFFunction.java:99)

at system.util.interactivejob_cfc$cf.udfCall3(/commandbox/system/util/InteractiveJob.cfc:365)

at system.util.interactivejob_cfc$cf.udfCall(/commandbox/system/util/InteractiveJob.cfc)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)

at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:771)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)

at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)

at system.util.interactivejob_cfc$cf.udfCall1(/commandbox/system/util/InteractiveJob.cfc:80)

at system.util.interactivejob_cfc$cf.udfCall(/commandbox/system/util/InteractiveJob.cfc)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)

at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:771)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)

at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)

at system.util.interactivejob_cfc$cf.udfCall1(/commandbox/system/util/InteractiveJob.cfc:105)

at system.util.interactivejob_cfc$cf.udfCall(/commandbox/system/util/InteractiveJob.cfc)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:687)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:567)

at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1988)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)

at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)

at system.services.serverengineservice_cfc$cf.udfCall(/commandbox/system/services/ServerEngineService.cfc:161)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)

at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:771)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)

at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)

at system.services.serverengineservice_cfc$cf.udfCall(/commandbox/system/services/ServerEngineService.cfc:57)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)

at lucee.runtime.type.scope.UndefinedImpl.callWithNamedValues(UndefinedImpl.java:780)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)

at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)

at system.services.serverengineservice_cfc$cf.udfCall(/commandbox/system/services/ServerEngineService.cfc:38)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:689)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:567)

at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:2005)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)

at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)

at system.services.serverservice_cfc$cf.udfCall1(/commandbox/system/services/ServerService.cfc:750)

at system.services.serverservice_cfc$cf.udfCall(/commandbox/system/services/ServerService.cfc)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:689)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:567)

at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:2005)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)

at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)

at system.modules_app.server_commands315.commands.server.start_cfc$cf.udfCall(/commandbox/system/modules_app/server-commands/commands/server/start.cfc:150)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:689)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:567)

at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:2005)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)

at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)

at system.services.commandservice_cfc$cf.udfCall1(/commandbox/system/services/CommandService.cfc:337)

at system.services.commandservice_cfc$cf.udfCall(/commandbox/system/services/CommandService.cfc)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)

at lucee.runtime.type.scope.UndefinedImpl.callWithNamedValues(UndefinedImpl.java:780)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)

at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)

at system.services.commandservice_cfc$cf.udfCall1(/commandbox/system/services/CommandService.cfc:138)

at system.services.commandservice_cfc$cf.udfCall(/commandbox/system/services/CommandService.cfc)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:687)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:567)

at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1988)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756)

at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1718)

at system.shell_cfc$cf.udfCall4(/commandbox/system/Shell.cfc:747)

at system.shell_cfc$cf.udfCall(/commandbox/system/Shell.cfc)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)

at lucee.runtime.type.scope.UndefinedImpl.callWithNamedValues(UndefinedImpl.java:780)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)

at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)

at system.shell_cfc$cf.udfCall3(/commandbox/system/Shell.cfc:570)

at system.shell_cfc$cf.udfCall(/commandbox/system/Shell.cfc)

at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)

at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)

at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:212)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:689)

at lucee.runtime.ComponentImpl._call(ComponentImpl.java:567)

at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:2005)

at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:833)

at lucee.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1737)

at joel_clegg230._commandbox46.cfml.system.bootstrap_cfm$cf.call(/__commandbox_root/joel.clegg/.CommandBox/cfml/system/Bootstrap.cfm:160)

at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:933)

at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:823)

at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:805)

at 8pp1b1u76mgd.call(Unknown Source)

at lucee.runtime.compiler.Renderer.tag(Renderer.java:113)

at lucee.runtime.compiler.Renderer.script(Renderer.java:101)

at lucee.runtime.jsr223.ScriptEngineImpl.eval(ScriptEngineImpl.java:64)

at lucee.runtime.jsr223.ScriptEngineImpl.eval(ScriptEngineImpl.java:199)

at cliloader.LoaderCLIMain.execute(LoaderCLIMain.java:283)

at cliloader.LoaderCLIMain.execute(LoaderCLIMain.java:150)

at cliloader.LoaderCLIMain.main(LoaderCLIMain.java:506)

CommandBox:myv2>

You should check out that module again. It’s had Mac support since it began I think and I think Chris changed it quite some time back to use sudo when editing the hosts file which allows you to type a password to set up your sudoers file. If it still needs some work, maybe you can send Chris a pull for it.

So, here’s what’s happening. You’re causing downstream issues for yourself when you try/catch the command executions. This really isn’t even related to native OS binaries. Any command that errors with the internal error() method from base command would have this issue. When the server starts starting, an interactive job is started. When error() gets called (in this case from your “run” command) it cancels all open interactive jobs, prints the error out to the screen, and throws an exception with the expectation that the entire stack trace will be rolled back to the shell’s prompt and no further execution will happen. (It cancels the open jobs to clean up after itself so they aren’t left open after the error).

So when you try/catch the command, the jobs are cancelled but you intercept (catch) the exception and try to get the server to keep starting, but now CommandBox is in an invalid state since there’s no active jobs but the server start command is trying to add job logs. You could run job.start() to start a new job in your catch if you wanted but that’s a bit of a hack at best. Here’s the docs on interactive jobs BTW:
https://commandbox.ortusbooks.com/task-runners/interactive-jobs

The long and short of it is that there’s no good way to recover from a command that errors out while inside of an interactive job. I’ll have to think on what we can do to improve this. It’s one of those things where in your case you’re running something you expect might fail and want to recover from it, but in most other scenarios I had thought through previously, it seemed correct that if a command nested inside another command failed, than it only made sense to cancel the whole kit and kaboodle.

I could delay the cancelling of the jobs until the stack trace rolls all the way back to the prompt (assuming it’s not caught first elsewhere) but then I run the risk of jobs being started that never get completed. The current method I went with was on the safe side since it always cleaned up after itself in the event of an error.