GradleUp / shadow

Gradle plugin to create fat/uber JARs, apply file transforms, and relocate packages for applications and libraries. Gradle version of Maven's Shade plugin.
https://www.gradleup.com/shadow/
Apache License 2.0
3.71k stars 392 forks source link

Why does startShadowScripts use eval instead of exec --> maybe use eval+exec #435

Open Space2Man opened 5 years ago

Space2Man commented 5 years ago

Shadow Version

4.0.3 (upgraded from 1.2.4)

Gradle Version

4.10.2

Expected Behavior

before commit 45497ff3031e904e70d755c2bc87526a9f62e049 the created start script was using exec to run the java command for application (APPNAME as example). Then it was possible to run something like

PID=./bin/APPNAME >/dev/null 2>&1 & echo $!

to get the PID of the java command.

Actual Behavior

After switching to eval the PID now contains the PID of the start script and not the PID of the java cmd.

Gradle Build Script(s)

n/a

Content of Shadow JAR (jar tf <jar file> - post link to GIST if too long)

n/a

Is it possible to combine eval + exec so that the parameters get evaluated and then are run by exec so we can get the PID of the java command in an easy way again?

Thanks and best regards,

Jochen
Space2Man commented 5 years ago

see how gradle handles this:

https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt

JamesXNelson commented 5 years ago

Wow. Unrelate to OP, but the very end of that gradle script may solve a long standing question of "why does random_script fail on a particular co-worker's Mac"... cwd is wrong if launched from Finder. Random, but makes me glad I spent some seconds to read.

Cellebyte commented 5 years ago

Proposal

PID=`./bin/appname.sh '"> log/stdout.log 2>&1 & echo $!"'`
Space2Man commented 5 years ago

I don't think this will work ... I need the PID of the java command that is started in ./bin/APPNAME.

  $      Expands to the process ID of the shell.  In a () subshell, it expands to the process ID of the current shell, not the sub‐
         shell.
  !      Expands to the process ID of the job most recently placed into the background, whether executed as an asynchronous command
         or using the bg builtin (see JOB CONTROL below).

If exec() is used then the PID of ./bin/APPNAME becomes the PID of the java command. But if eval() is used then you can only find the PID of the shell that's executing ./bin/APPNAME or the current shell.

$ cat ./fooeval.sh 
#!/bin/sh
eval sleep 300
$ ./fooeval.sh & echo $$ $!
[1] 25926
25608 25926
$ ps -e | grep sleep
25927 pts/9    00:00:00 sleep
$ ps -e | grep 25926
25926 pts/9    00:00:00 fooeval.sh
$ ps -e | grep 25608
25608 pts/9    00:00:00 bash

See, this is not working ... but if you use exec() and $!:

$ cat ./fooexec.sh 
#!/bin/sh
exec sleep 300
$ ./fooexec.sh & echo $$ $!
[1] 28477
25608 28477
$ ps -e | grep sleep
28477 pts/9    00:00:00 sleep

Then it works fine.

Cellebyte commented 5 years ago

Solution

Will be fixed by: #455

Workarround

Mask the parameters to forward them to the underlying process.

${START_SCRIPT} '"> log/stdout.log 2>&1 & echo $!"'