I've got a chain of scripts that work as expected when invoked from the command line, but if the same user is running TomCat as a service under the same account Start-Process appears to return without doing anything.
My question is, is there something inherently different the environment built during a command executed from Java? Any pointers would be helpful.
Invocation from Command Line
If I issue the command cmd /c c:\test\test.bat when logged in as cuser1 at a non-elevated command prompt, I see the following log:
HS0\cuser1 called script as HS0\cuser2
Script running as HS0\cuser2
Invocation from Java Process
If I issue the same command using Runtime.getRuntime().exec() from inside my TomCat application, I don't see the switch.
List<String> cmd = new ArrayList<>();
cmd.add("cmd");
cmd.add("/c");
cmd.add("C:\\test\\test.bat");
final Process process = Runtime.getRuntime().exec(cmd);
...
// Handling the command output, nothing in the output, no error result
Instead, I only see the first line of the log. I've been catching exceptions, looking at exceptions and reading the output of the command, but it appears that the Start-Process command returns immediately without an error code. This is obviously test code with hardcoded credentials and not the real deal, but I can see the same behavior in this simplified code.
The Test
c:\test\test.bat => calls a PowerShell script
c:\test\test-switch.ps1 => invokes a PowerShell script as different user
c:\test\test.ps1 => display current user
test.bat
PowerShell -NoProfile -ExecutionPolicy Bypass -File "c:\test\test-switch.ps1"
test-switch.ps1
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$pwd = ConvertTo-SecureString "password" -asplaintext -force
$cred = New-Object System.Management.Automation.PSCredential ("HS0\cuser2", $pwd)
$args = "-NoProfile -ExecutionPolicy Bypass -File c:\test\test.ps1"
Start-Process Powershell -Credential $cred -ArgumentList $args
"$currentUser called script as HS0\cuser2" | Out-File 'c:\test\test.log' -Append
test.ps1
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
"Script running at $(Get-Date) as $currentUser" | Out-File 'c:\test\test.log' -Append
Related
In the start script for my application, the service is started with the following lines:
JVM_OPTS=$DEFAULT_JVM_OPTS" "$JAVA_OPTS" "$${optsEnvironmentVar}" -Dapp.pid=$$ -Dapp.home=$APP_HOME -Dbasedir=$APP_HOME"
exec nohup "$JAVACMD" -jar $JVM_OPTS <% if ( appNameSystemProperty ) { %>\"-D${appNameSystemProperty}=$APP_BASE_NAME\" <% } %> $CLASSPATH server /resources/config.yml > /home/testUser/stdout.out 2> /home/testUser/stderr.err &
The application starts up fine, but on code review, we noticed that the value of -Dapp.pid was incorrect, by checking it in ps -aux | grep appName, and comparing it to the PID of that command, along with the PID outputed by pgrep -f appName. I would like to know if there is any way to assign the correct PID to the parameter. So far, I've tried setting it to be:
-Dapp.pid=`preg -f appName`
But that simply ends up with -Dapp.pid being blank, which I assume is due to it calling that command before the exec is fully run. Has anyone else come across this before?
I'm developing Linux expect script that:
makes ssh connection to Windows host command prompt.
Accesses powershell.
Navigates to existing folder on windows and invokes a powershell script.
Power shell script saves output to a text file.
When I run Linux script using Java, the powershell is executed successfully. However, output file created by powershell script is only 80 chars wide.
When I run the script manually (via terminal and pass arguments manually), the output file is created without new lines after 80 chars.
I've tried to change encoding to utf8 and utf16 in powershell, but it doesn't resolve the issue
Get-MsolDomainFederationSettings -DomainName "example.com" | Out-File "C:\temp\fedSettings.txt"
Get-MsolDomainFederationSettings -DomainName "example.com" | Format-List * | Out-File "C:\temp\fedSettings.txt" -Encoding utf8
Get-MsolDomainFederationSettings -DomainName "example.com" | Format-List * | Out-File "C:\temp\fedSettings.txt" -Encoding utf16
I have also, ensured that the expect scripts do not have any Ctrl+M characters.
This is script that I execute via java ProcessBuilder
#!/usr/bin/expect
set timeout 20
#This expect script script invokes an existing script in Windows Powershell on a Windows Host via SSH from Linux.
set WINDOWS_HOST_NAME [lindex $argv 0]
set WINDOWS_USER [lindex $argv 1]
set WINDOWS_PASSWORD [lindex $argv 2]
set WINDOWS_FOLDER_PATH [lindex $argv 3]
set SCRIPT_FILE_NAME [lindex $argv 4]
spawn ssh $WINDOWS_USER#$WINDOWS_HOST_NAME
expect "yes/no" {
send "yes\r"
expect "*?assword" { send "$WINDOWS_PASSWORD\r" }
} "*?assword" { send "$WINDOWS_PASSWORD\r" }
expect "*$WINDOWS_USER*"
send "powershell\r";
send "cd $WINDOWS_FOLDER_PATH\r"
send "\.\\$SCRIPT_FILE_NAME\r"
send "exit\r"
send "exit\r"
interact
This is the powershell script that exists in windows and gets invoked by linux script.
$AdminUser = "someone.com"
$Pswd = Get-Content "C:/creds/cred1" | ConvertTo-SecureString
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminUser, $Pswd
$dom = "example.com"
$dateTime = Get-Date -f "MMddyyyy_HHmm"
Connect-MsolService -Credential $cred
Get-MsolDomainFederationSettings -DomainName $dom | Format-List * | Out-File "C:\temp\fedSettings.txt"
$filenameFormat = "fedSettings_$(Get-Date -Format "MMddyyyy_HHmm").txt"
Rename-Item -Path "C:\temp\fedSettings" -NewName $filenameFormat
I'm expecting that when PowerShell creates an output file, the new line is introduced only if content/data of the line is complete.
However, the output file created is limited to only 80 chars when executed via java/automated.
But, when I execute the expect script manually, then, the file is fine.
I have Nodejs - server.js code in my windows system from which i want to execute a simple jar file.
So i used follwoing code :
cmd = "java -jar C:\\libs\\sample.jar";
var Exec =exec(cmd, function(error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
}//end of if
});//end of exec cmd
When i run the "node server.js" in command prompt ,jar is executing perfectly.
After this i made this "node server.js" command as service by referring following link :
https://github.com/coreybutler/node-windows
i.e node-windows,But now once its become service i am unable to exectue simple.jar,even i am enble to run simple "java -version" command.
Except java all other command are working fine even after i made nodejs as service.
Please help me out.....
New Update : After testing lot of different cases, Finally i came to know that jars containing JFrame components is not opening...how to solve this
When I run myTest.jar, it outputs alot of information in STDOUT (not in a file) and I am trying to read/search that file for a specific string to put as a variable in my bash script.
java stdout:
line 1 info............
line 2 info...........
....
...
Successful (either 'Successful' or 'Failed')
How do I search for, in bash, the last line in the stdout or for ('Successful' or 'Failed') without redirecting the stdout to a file?
Thanks in advance
This is not a good way of checking for success or failure.
You should instead rewrite myTest.jar to use System.exit(0) on success and System.exit(1) (or higher) on error. If the program is well written, it will already do this.
You can then check for success or failure in bash using e.g.
if java -jar mytest.jar
then
echo "The command succeeded :D"
else
echo "The command failed :("
fi
All UNIX programs work this way, and you should make sure that myTest.jar is no exception.
To make this work, you would need to redirect stdout to a file and then cat/vim/search that file. Bash doesn't save the output of commands on its own.
Alternatively, you could use a program like screen that allows you to save a transcript of your session to a file. You would get the output of everything and the command lines though.
for future users, I used "that other guys' " method with some minor adjustments:
1) the exit code and what your doing have to be right after the running jar, wouldn't work for me in other segments
2) I read the exit code I was receiving and made an if loop for my conditions (0-2) exit code was given in java
3) piece of my bash code
EXIT_CODE=$?
echo Exit code: $EXIT_CODE
if [ $EXIT_CODE = "0" ]
then
...............do something
elif [$EXIT_CODE = "1"]
then
...............do something
else
...............do something
fi
When I run the same command from Java via Runtime.getRuntime I get the return code 6. The same command works fine from command line:
process = Runtime.getRuntime().exec(mysqldumpCommand);
int processComplete = process.waitFor();
For those 2 commands I get the return code 6 when run from java and no dump. The work fine from command line(I don't have a password on the local env.)
mysqldump --user=root --password= --host=localhost dbname > c:\temp\dumpfile.sql
mysqldump --user=root --password="" --host=localhost dbname > c:\temp\dumpfile.sql
When deliberately put wrong password I get return code 2 in java, and a connection error in command line:
mysqldump --user=root --password= --host=localhost dbname > c:\temp\dumpfile.sql
The return codes as I found them here:
Taken from client/mysqldump.c in MySQL 5.1.59:
#define EX_USAGE 1
#define EX_MYSQLERR 2
#define EX_CONSCHECK 3
#define EX_EOM 4
#define EX_EOF 5 /* ferror for output file was got */
#define EX_ILLEGAL_TABLE 6
How come I get (error) return code 6 when running the same command in java and works fine from command line?
Later Edit: I try it from Windows.
Runtime.exec is not a shell, so redirections with > and < won't work. Currently the command is passing > to mysqldump, which interprets it as the name for the table you want to export. (Hence return code 6, "illegal table".)
There are two solutions:
Run a shell. Use this command instead of the one you have:
cmd.exe /c "mysqldump --user=root --password= --host=localhost dbname > c:\temp\dumpfile.sql"
Write the output from the command to a file yourself, with Process.getInputStream().
The mysqldump now supports --result-file=
So it would look like this.
mysqldump --user=root --password= --host=localhost dbname --result-file=c:\temp\dumpfile.sql