Terminal on Mac is not opening when a .sh file is executed from Katalon

I am trying to run an executable .sh file from Katalon using the below code, but my mac terminal is not opening and running the file, any idea how to perform this operation?

Runtime.getRuntime().exec("./Automation.sh");

Test gets passed but terminal will not open and run the script !!

https://www.baeldung.com/run-shell-command-in-java gives a sample code. In it you will find

    process = Runtime.getRuntime()
      .exec(String.format("sh -c ls %s", homeDirectory));

Please find that this sample executes sh command (possibily bash executable) which will be found in the $PATH environment variable of OS, so it will successfully run.

In you code you passed a String "./Automation.sh" which will not be found in the $PATH, and it is not executable, so your code will never run.

You have an misunderstanding.

The “Terminal app of Mac” has nothing to do with your case.

When a Java program calls Runtime.getRuntime().exec(..), it speaks to the OS on which the program is running. It does not speak to the “Terminal” app at all.

1 Like

Let us not confuse people.
Although you are right, the exec() will speak to the OS (and not call terminal which is yet another app), when we speak about sh scripts we have to first talk about shells.

$PATH it is just … a path where the OS may look for various executable’s (binaries) but not a binding for a specific one.

But, in the case of Linux at least, the sh binding it is not made in the $PATH, but in the environment in use, which may vary from user to user ($PATH is just a variable inside this guy).
It is an alias which can point to various executables (bash, zsh, csh and so on).
See:

$ echo $PATH
/home/ibus/.local/bin:/home/ibus/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/var/lib/snapd/snap/bin

vs:

$ env | grep sh
SHELL=/bin/bash

vs

env | grep PATH
PATH=/home/ibus/.local/bin:/home/ibus/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/var/lib/snapd/snap/bin

Most probably same it is on Mac, since it is also an *unix OS despite whatever fans may think.
So, knowing your OS in depth may help you to avoid headache.
But yeah, @kazurayam 's comment are somehow valid … pay more attention when using code snippets found here and there …

LE: and of-course, all from above can be enforced to a specific shell <> terminal for a specific script through the use of a shebang but i will let you read more about this by using various searches …

1 Like

@bionel

Thank you for your comment. I would accept all you wrote above.

thanks for the solution @kazurayam, but it’s not working, my test case shows passed, but the terminal is not opening !!

@surajigure09 this is because the command gave to you:

.exec(String.format("sh -c ls %s", homeDirectory));

will run a shell but not a terminal session (read my above notes and the insights from @kazurayam again )
If you really need to open terminal, consult your OS doc’s on how to run Terminal from command line and pass a script as an argument.
Although, why do you need that? Does your script wait for user input?

1 Like

Do you want to open a window of Terminal.app on Mac by your Java/Groovy program?


I do not know how to write a Groovy/Java program that opens a window of Terminal app on Mac. To be precise, I do not know the absolute path of the executable “Termianl app”, and I do not know if it is possible to launch it in the command line.

I am not interested in it, as I can open a window of Terminal.app with my finger by clicking this icon スクリーンショット 2022-03-04 18.16.16 on the desktop of Mac. It’s enough for me.

@kazurayam - Yep, that’s correct, I want to open the terminal and run the .sh shell script file by using the java/groovy program.

I did the same on a windows machine with a .bat file and works fine over there, I am trying to do the same on mac.

I have all data like token, path and other variables set in a properties file, so when i run the .sh file, it will pick the info from there and execute it. Manually running from terminal works fine.

an sh file is just a script. a shell script if the content is right.
period.

no, you didn’t. this is the defective behaviour of windows command interpreter.
any sane OS won’t behave like this.

@bionel - I understand your book knowledge and what u r trying to say, but you are not giving me a solution :slight_smile: please give a solution or say if it can be achieved or not…

@bionel u want to see a video of what I am doing in windows, without knowing what I am doing how can u say the defective behaviour of the Windows command interpreter.

give me a solution on how to open a terminal using groovy or java program, or rather say u don’t know :slight_smile: and keep quiet plz.

i allready gave u solutions.
and you still didnt answered to the most relevant question.
why do you exactly need such?
for the rest just keep dreaming that how a script behaves on windows platform is the sane way…

@bionel - please read the discussion that happened between me and @kazurayam - that is exactly what I need.

Do you want to open a window of the Terminal.app on Mac by your Java/Groovy program? - and I answered yes, can u give me a solution for this?

why do I need it? - instead of manually going to the terminal and running the script, I want that to be automated !!

Let me summarize it better for you @bionel @kazurayam - To avoid Confusions !!

  1. In the screenshot below you can see the test case I am trying to run, I need help with a proper command/program to run the shell script from katalon. Even if the terminal is opening or not, at least if it can display inside the console if the sh script is even executing. The .bat file I am referring in screenshot is to show you that it works in windows with that line of code. Looking something similar on mac.

OK. Now I understand what you want to do.

Let me show you a solution.

In the Katalon Studio projects’ folder, I made a shell script <projectDir>/Automation.sh:

#!/bin/sh

# call this function to write into stderr
echo_stderr()
{
  echo "$@" >&2
}

# write to stdout
echo this is stdout

# write to stderr
echo_stderr this is stderr

I made a Test Case script Test Cases/TC1:

import java.nio.file.Path
import java.nio.file.Paths

/**
 * https://www.baeldung.com/java-process-api
 * 8. Handling Process Stream
 */
Path projectDir = Paths.get(System.getProperty("user.dir"))
Path shellFile = projectDir.resolve("Automation.sh")

 Process process = new ProcessBuilder("sh", shellFile.toString()).start()
 
BufferedReader stderr = 
 	new BufferedReader(
		 new InputStreamReader(process.getErrorStream()));
 
BufferedReader stdout =
	 new BufferedReader(
		 new InputStreamReader(process.getInputStream()));

String errString = stderr.readLine()
String outString = stdout.readLine()

System.out.println("stderr: " + errString)
System.out.println("stdout: " + outString)

When I ran TC1, I saw the following output in the Console of Katalon Studio GUI:

2022-03-05 09:20:02.850 DEBUG testcase.TC1                             - 8: out.println("stderr: " + errString)
stderr: this is stderr
2022-03-05 09:20:02.878 DEBUG testcase.TC1                             - 9: out.println("stdout: " + outString)
stdout: this is stdout

Here you can see the output from the subprocess (the shell script) is consumed by the parent process (Test Case).

I do not need to open a window of “Terminal.app” at all. This code will work just the same on Mac, Linux and Windows.

See https://www.baeldung.com/java-process-api for further tutorial. Quoting from this article:

8. Handling Process Streams

By default, the created subprocess does not have its terminal or console. All its standard I/O (i.e., stdin, stdout, stderr) operations will be sent to the parent process. Thereby the parent process can use these streams to feed input to and get output from the subprocess.

Consequently, this gives us a huge amount of flexibility as it gives us control over the input/output of our sub-process.

Just for your interest:

I have developed a library that wraps java.lang.ProcessBuilder, which implements various helper methods; especially useful when you want to startup & shutdown HTTP server process in the command line from Java app.

As an alternative, you can redirect the output of your script to a log file if you don’t need to check it real time, but later.
sort of:

myscript.sh > /path/to/logfile.log

@bionel

Shell’s redirection operator > does not work in a Java/Groovy program.

I wrote a Test Case of single line:

process = Runtime.getRuntime().exec("sh -c ls . > out.txt")

I ran it. It passed. But the file out.txt was not created.

Why?

I would tell you why.

When Runtime.getRuntime().exec("sh -c ls .") ran, it creates a subprocess. The output stream from the subprocess is implicitly redirected to the parent process (the Test Case in Katalon Studio). The above single line script does not consume the stream, therefore the content of the stream is eventually thrown away.

The Runtime.getRuntime().exec( ... ) does not understand the > symbol at all. The > is a special symbol understood only by Shell command line interpreter. The Runtime.getRuntime().exec( ... ) does NOT behave the same as a Shell command line interpreter.

I wrote a variation.

process = Runtime.getRuntime().exec("sh -c ls .")

BufferedReader stdout =
    new BufferedReader(
	    new InputStreamReader(process.getInputStream()));
String line
while ((line = stdout.readLine()) != null) {
	println line
}

When I ran this, I saw the following output in the Console

2022-03-06 09:46:20.102 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/TC1
Checkpoints
Data Files
Drivers
Include
Keywords
Libs
Object Repository
Plugins
Profiles
Reports
Scripts
Test Cases
Test Listeners
Test Suites
VisualInspectionOfExcelAndPDF.prj
bin
build
build.gradle
console.properties
settings
store
2022-03-06 09:46:20.816 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/TC1

The lines after BufferedReader ... do the same processing as the > in the Shell interpreter.

Cumbersome? … Yes, it is really cumbersome.

This demo reminds us how nicely the “UNIX Shell interpreter” was designed by Ken Thompson in 1970s. It is really amazing.

1 Like