I've written a build script:
task hello // 1
hello << { // 2
println "task hello"
}
hello << { // 3
println "another task hello"
}
As I've understood //1 defines an object of Task type, //2 and //3 applies leftShift(Closure c) operator to that task. When I ran that script with command gradle -q hello I saw the following output:
task hello
another task hello
Taking that into account can we say that gradle -q task_name executes all closure's body to which operator << was applied or the command has another meaning?
gradle -q hello sets logging level to quiet (printlns are logged at that level and hence will still be shown) and executes task hello. Executing a task means executing all its task actions. Your build script adds two task actions, which will be executed in the order they were added. (<< is an alias for doLast, which adds a task action to the end of a task's list of task actions).
# gradle -h
...
-q, --quiet Log errors only.
...
No, -q switch is used to suppress all the messages that are logged to console (except error level) and print statement.
If You execute the following script:
task lol
lol << {
println '1'
}
lol << {
logger.lifecycle '2'
}
without -q switch You'll get both 1 and 2 in output. With -q switch only 1 will be printed.
<< operator is completely different thing - it's used to add action to a task. See this answer for details.
Related
I've a JavaFX application where I've a list of a bunch of script files. Once the application loads, it reads it and and checks which ones are running.
To do that I use a ProcessHandle, as mentioned in various examples here on StackOverflow and other guides/tutorials on the internet.
The problem is, it never finds any of them. There for I programmatically started one, which I know for a fact that it will be running, via Process process = new ProcessBuilder("/path/to/file/my_script.sh").start(); - and it won't find this one either.
Contents of my_script.sh:
#!/bin/bash
echo "Wait for 5 seconds"
sleep 5
echo "Completed"
Java code:
// List of PIDs which correspond to the processes shown after "INFO COMMAND:"
System.out.println("ALL PROCESSES: " + ProcessHandle.allProcesses().toList());
Optional<ProcessHandle> scriptProcessHandle = ProcessHandle.allProcesses().filter(processHandle -> {
System.out.println("INFO COMMAND: " + processHandle.info().command());
Optional<String> processOptional = processHandle.info().command();
return processOptional.isPresent() && processOptional.get().equals("my_script.sh");
}).findFirst();
System.out.println("Script process handle is present: " + scriptProcessHandle.isPresent());
if (scriptProcessHandle.isPresent()) { // Always false
// Do stuff
}
Thanks to the good old fashioned System.out.println(), I noticed that I get this in my output console every time:
ALL PROCESSES: [1, 2, 28, 85, 128, 6944, 21174, 29029, 29071]
INFO COMMAND: Optional[/usr/bin/bwrap]
INFO COMMAND: Optional[/usr/bin/bash]
INFO COMMAND: Optional[/app/idea-IC/jbr/bin/java]
INFO COMMAND: Optional[/app/idea-IC/bin/fsnotifier]
INFO COMMAND: Optional[/home/username/.jdks/openjdk-17.0.2/bin/java]
INFO COMMAND: Optional[/usr/bin/bash]
INFO COMMAND: Optional[/home/username/.jdks/openjdk-17.0.2/bin/java]
INFO COMMAND: Optional[/home/username/.jdks/openjdk-17.0.2/bin/java]
INFO COMMAND: Optional[/usr/bin/bash]
Script process handle is present: false
The first line in the Javadoc of ProcessHandle.allProcess() reads:
Returns a snapshot of all processes visible to the current process.
So how come I can't see the rest of the operating system's processes?
I'm looking for a non-os-dependent solution, if possible. Why? For better portability and hopefully less maintenance in the future.
Notes:
A popular solution for GNU/Linux seems to be to check the proc entries, but I don't know if that would work for at least the majority of the most popular distributions - if it doesn't, adding support for them in a different way, would create more testing and maintenance workload.
I'm aware of ps, windir, tasklist.exe possible solutions (worst comes to worst).
I found the JavaSysMon library but it seems dead and unfortunately:
CPU speed on Linux only reports correct values for Intel CPUs
Edit 1:
I'm on Pop_OS! and installed IntelliJ via the PopShop as flatpak.
In order to start it as root as suggested by mr mcwolf, I went to /home/username/.local/share/flatpak/app/com.jetbrains.IntelliJ-IDEA-Community/x86_64/stable/active/export/bin and found com.jetbrains.IntelliJ-IDEA-Community file.
When I run sudo ./com.jetbrains.IntelliJ-IDEA-Community or sudo /usr/bin/flatpak run --branch=stable --arch=x86_64 com.jetbrains.IntelliJ-IDEA-Community in my terminal, I get error: app/com.jetbrains.IntelliJ-IDEA-Community/x86_64/stable not installed
So I opened the file and ran its contents:
exec /usr/bin/flatpak run --branch=stable --arch=x86_64 com.jetbrains.IntelliJ-IDEA-Community "$#"
This opens IntelliJ, but not as root, so instead I ran:
exec sudo /usr/bin/flatpak run --branch=stable --arch=x86_64 com.jetbrains.IntelliJ-IDEA-Community "$#"
Which prompts for a password and when I write it in, the terminal crashes.
Edit 1.1:
(╯°□°)╯︵ ┻━┻ "flatpak run" is not intended to be ran with sudo
Edit 2:
As mr mcwolf said, I downloaded the IntelliJ from the official website, extracted it and ran the idea.sh as root.
Now a lot more processes are shown. 1/3 of them show up as INFO COMMAND: Optional.empty.
scriptProcessHandle.isPresent() is still unfortunately returning false. I searched through them and my_script.sh is nowhere to be found. I also tried processOptional.isPresent() && processOptional.get().equals("/absolute/path/to/my_script.sh") but I still get false on isPresent() and it's not in the list of shown processes.
Though the last sentence might be a different problem. I'll do more digging.
Edit 3:
Combining .commandLine() and .contains() (instead of .equals()) solves the problem mentioned in "Edit 2".
Optional<ProcessHandle> scriptProcessHandle = ProcessHandle.allProcesses().filter(processHandle -> {
System.out.println("INFO COMMAND LINE: " + processHandle.info().commandLine());
Optional<String> processOptional = processHandle.info().commandLine();
return processOptional.isPresent() && processOptional.get().contains("/absolute/path/to/my_script.sh");
}).findFirst();
System.out.println("Script process handle is present: " + scriptProcessHandle.isPresent());
if (scriptProcessHandle.isPresent()) { // Returns true
// Do stuff
}
.commandLine() also shows script arguments, so that must be kept in mind.
I'm using Gradle. I have two tasks: "a" and "b". I want task "a" to call task "b". How can I do this?
task b(type: Exec) {
description "Task B"
commandLine 'echo', 'task-b'
}
task a(type: Exec) {
description "Task A"
commandLine 'echo', 'task-a'
// TODO: run task b
}
In Ant this is a piece of cake:
<target name="a">
<echo message="task-a"/>
<antcall target="b"/>
</target>
<target name="b">
<echo message="task-b"/>
</target>
The first method I tried is using the "dependsOn" feature. However this is not ideal as we would need to think of all the tasks in reverse and also has several other issues (like running a task when a condition is satisfied).
Another method I tried is:
b.mustRunAfter(a)
However this only works if I run the gradle tasks like so:
gradle -q a b
Which is also not ideal.
Is there anyway to simply just call another task from an existing task?
As suggested one method would be to add a finalizer for the task
task beta << {
println 'Hello from beta'
}
task alpha << {
println "Hello from alpha"
}
// some condition
if (project.hasProperty("doBeta")) {
alpha.finalizedBy beta
}
Then we can execute the other task if needed. As for executing tasks from another tasks you cannot do that. Task declaration is declarative not imperative. So a task can depend on another task but they cannot execute another task.
$ gradle -q alpha
Hello from alpha
$ gradle -q alpha -PdoBeta
Hello from alpha
Hello from beta
You can use
a.dependsOn 'b'
Or
a.dependsOn b
Or
task a(type: Exec, dependsOn: 'b') { ... }
etc
See adding dependencies to tasks
To summarize and combine the answers from #JBirdVegas and #lance-java, using non-deprecated doLast instead of leftShift (<<):
task beta {
doLast {
println 'Hello from beta'
}
}
task alpha {
doLast {
println 'Hello from alpha'
}
}
// some condition
if (project.hasProperty('doBeta')) {
alpha.finalizedBy beta // run 'beta' after 'alpha'
// or
// alpha.dependsOn beta // run 'beta' before 'alpha'
}
It is working fine but providing a warning as Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
I am using gradle version 4.7. So it means some of the features you have added in the build.gradle will not work as it is in gradle 5.0.
Run the Gradle build with a command line argument --warning-mode=all to see what exactly the deprecated features are.
It will give you a detailed description of found issues with links to the Gradle docs for instructions how to fix your build.
Basically I have 4 tasks that I need to run sequentially, but I cannot make them do so, I have to run it one by one on the command line as so:
gradle :drmdexsecondary:compileReleaseJava --info --debug --stacktrace
gradle :drmdexsecondary:dexClasses --info --debug --stacktrace
gradle :drmdexsecondary:jar --info --debug --stacktrace
Here's my build.gradle:
evaluationDependsOnChildren();
task dexClasses( type:Exec ) {
// compileJava.execute()
String cmdExt = Os.isFamily(Os.FAMILY_WINDOWS) ? '.bat' : ''
println("${buildDir}")
println("${androidSdkDir}\\build-tools\\${buildToolsVersion}\\dx${cmdExt} --dex --output=${buildDir}\\classes\\classes.dex ${buildDir}\\classes\\release")
commandLine "cmd", "/c", "${androidSdkDir}\\build-tools\\${buildToolsVersion}\\dx${cmdExt} --dex --output=${buildDir}\\classes\\classes.dex ${buildDir}\\classes\\release"
}
task jar(type: Jar) {
from ("${buildDir}\\classes\\classes.dex")
}
My problem is this:
the dependsOn keyword doesn't work... it just get ignored without any log message
taskname.execute() function doesn't work... it just get ignored without any log message
compileReleaseJava is not recognized inside build.gradle with this particular error: Could not find property 'compileJava' on task ':drmdexsecondary:dexClasses'.
Would anyone please help?
I've consulted and copy paste from the documentation but none of them seems work. I've even tried to re-install Gradle... there is so few sample codes there and although I understand the concept, it seems so difficult to translate my intention into working Gradle code, so if there is any good resources to help, it will be very appreciated as well.
You should read about gradle tasks and more about tasks. You want to depend on things rather then invoke things.
Also I think you should read about, and use the gradle android plugin.
To your original question, when you define a task the code between the braces is run at configuration time. A task's actions are run when the task is executed and must be added to the task's action list. This is done by using the task's doFirst, doLast or the << operator.
Here is an example from the gradle documentation.
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
task taskZ << {
println 'taskZ'
}
taskX.dependsOn taskY
taskY.dependsOn taskZ
taskZ.shouldRunAfter taskX
task1.finalizedBy task2 will run task2 after task1.
The Best Answer is Here
task myTask1() {
println("this is task1 running")
}
task task2() { dependsOn myTask1
println("this is task2 running")
}
when you execute gradle task2 .
this wil first execute task1 ,and then execute task2
you should use dependsOn key words
For example
task buildMyApk(type: Exec) {
def myCommond = ['gradle', "assembleRelease"]
commandLine myCommond
}
task moveApkFileToProjectFolder() { dependsOn buildMyApk
def releaseApkFilePath = "${buildDir}/outputs/apk/release/"
def targetApkFolder = "${rootProject.getProjectDir()}/apkFolder"
mkdir "${targetApkFolder}"
copy{
from releaseApkFilePath
into targetApkFolder
}
}
above answer will not work
task moveApkFileToProjectFolder run ,will first run buildMyApk.
my example task ,first will build apks .and then move apk File to my Project/apkFile folder .and execute success.
You can create a task of type GradleBuild and define the tasks inside of that task.
task releaseAfterMath(type: GradleBuild) {
tasks = [
'clean',
'build',
'publish',
'publishToMavenLocal',
'commitNewVersionTask',
'gitChangelogTask',
'commitChangelogTask'
]
}
And you can trigger releaseAfterMath like any other task. Running code here:
https://github.com/tomasbjerre/gradle-scripts/
For sequential or whatever the sequence you want to run your tasks, I do the following thing in my build.gradle file:
def modules = ["X", "Y", "Z", "ZZ"]
if (modules.size() > 1) {
for(j in 1 .. modules.size()-1 ) {
tasks[modules[j]].mustRunAfter modules[values[j-1]]
}
}
In our company we use Jython for some reason. I need to extend it with the ExpectJ, but I could not figure out how to do it.
I managed to download the expectj-2.0.7.jar, expectj-2.0.7-sources.jar and expectj-2.0.7-javadoc.jar files and made them accessible to Jython and Java itself as well.
So I can import it in my python script and JVM also finds the jars (by using a classpath loader hack). But according to ExpectJ's docs, something is still wrong.
import expectj
ex = expectj.ExpectJ() # I cannot use the second form of the
# constructor where I can pass a timeout
# parameter
sh = ex.spawn(targetshell, 22, usr, passw) # There is no spawn method in
# ExpectJ - but why???
This is where I'm getting stuck. Why doesn't the ExpectJ object have a spawn method? Does anyone have a solution for this?
The following solution is to ensure that spawned process completes before executing the next command. It guarantees the cycle 'send - expect - wait for completion of the command sent in send' and then 'send again - expect again - wait for completion' .
In order to wait for command prompt to finish executing the spawned process, use shell.expect(""). If in case there are further expectJ send and expect commands after this, sequential execution can be ensured. If there is no shell.expect("") the next step shell.send("exit\n") is executed without waiting for the completion of the process that it has already spawned, in the following case scp command is put to completion before next command is issued.
import expectj
expectinator = expectj.ExpectJ();
shell = expectinator.spawn(expectj.SshSpawn(host_name, 22, usr_name, ssh_pwd));
shell.send("scp -r src:usr:dest" + "\r")
shell.expect(remote_box_usr + "'s password:");
shell.send(ssh_pwd + "\r");
shell.expect("");
shell.send("exit\n");
shell.expectClose();
I want to perform an svn delete from my Grails app. I tested out both of the following in the Grails console:
"svn delete /usr/share/mydir".execute()
Runtime.getRuntime().exec("svn delete /usr/share/mydir")
In both cases, a instance of java.lang.Process is returned, but the command does not get executed (/usr/share/mydir is not deleted).
This behaviour only happens when the app is running on Linux (Ubuntu). If I run it on Windows, the command does get executed.
Update
Following Tim's advice in the comments, I changed the command so that it captures the process output:
def process = "svn delete /usr/share/mydir".execute()
def out = new StringBuilder()
process.waitForProcessOutput(out, new StringBuilder())
println "$out"
I now see that the reason it's failing is because:
error svn: Can't open file '/usr/share/mydir/.svn/lock': Permission
denied
The below code works fine for me on CentOS.
def scriptCom="/folderlocation/shellscript.sh"
println "[[Running $scriptCom]]"
def proc = scriptCom.execute()
def oneMinute = 60000
proc.waitForOrKill(oneMinute)
if(proc.exitValue()!=0){
println "[[return code: ${proc.exitValue()}]]"
println "[[stderr: ${proc.err.text}]]"
return null
}else{
println "[[stdout:$revisionid]]"
return proc.in.text.readLines()
}