This is an extremely strange situation, but I just cannot point out what I'm doing wrong.
I'm executing a big bunch of SQL scripts (table creation scripts, mostly). They are executed through Java, using sqlcmd. Here's the sqlcmd command I use.
sqlcmd -m 11 -S SERVER -d DB -U USER -P PASS -r0 -i "SCRIPT.sql" 2> "ERRORS.log" 1> NULL
Note: I use the -r0 and redirects to make sure only errors go into the log file. I chuck out all STDOUTs.
Now I execute this command in Java, using getRuntime.exec(), like this.
Runtime.getRuntime().gc();
strCmd = "cmd /c sqlcmd -m 11 -S SERVER -d DB -U USER -P PASS -r0 -i \"SCRIPT.sql\" 2> \"ERRORS.log\" 1> NULL"
Process proc = Runtime.getRuntime().exec(strCmd);
proc.waitFor();
Note: I use cmd /c, so that the command runs in its own shell and exits gracefully. Also, this helps in immediately reading the error log to look for errors.
The Problem!
This command works perfectly when run by hand on the command prompt (i.e. the tables are getting created as intended). However, when executed through Java as shown, the scripts are run, and and there are no errors, no exceptions, nothing in the logs. But, when checking in SSMS, the tables aren't there!
Where do I even begin debugging this issue?
UPDATE: I'M A MORON
The return value from the getRuntime().exec method is 1. It should be 0, which denotes normal execution.
Any pointers on how to fix this?
UPDATE 2
I've looked at the process' ErrorStream, and this is what it has.
Sqlcmd: Error: Error occurred while opening or operating on file 2>
(Reason: The filename, directory name, or volume label syntax is
incorrect).
Looks like the path I'm passing is wrong. The error log goes into my profile directory, which is C:\Documents and Settings\my_username. Do the spaces in the path matter? I'm anyways double-quoting them!
Have a look at the exec method with an string array as parameter:
java.lang.Runtime.exec(String[] cmdArray)
The JavaDoc for this method says:
Executes the specified command and arguments in a separate process.
So, the first item in the array is the command and all of your arguments are appended to the array, e. g.,
Runtime.getRuntime().exec(new String[] {"cmd", "/c", "sqlcmd ... "});
After looking at your comment and the implementation of exec(String) it seems to be, that the exec method recognizes the pipe operator > as an argument to cmd, because exec(String) splits the command string to an array using whitespaces as seperators.
I don't have privs to post comments - which is what this is - but what if you try putting in a bogus user id for the DB? Does that cause a different execution path? Will that give you a Java error? Or an Auth error in your DB? Also, def tweak the user, not the password and learn from my experience that if you tweak the password that's a great way to get an account locked out!
The other thing - and this may be a shot in the dark - but what are the JRE and driver you're using? I believe there's a known issue with JRE 1.6.0.29 and the sqljdbc4 JAR. I have more details on this, but I'll have to post the link once I get to work.
Edit:
I know it's been established that the JRE/sqljdbc combo isn't your issue, but if folks search and find this, here is the link I spoke of above:
Driver.getConnection hangs using SQLServer driver and Java 1.6.0_29
First enable log/view commands output (since exec() returns 1), which would point out possible cause of the issue.
Use proc.getInputStream() and print the contents to a file or console.
Related
QUESTION: What does each element of the command:
pkill -INT -f '^php test_program.php$'
do when I run it in the linux terminal? I already know that the command kills the process called test_program.php, but I don't know what all the different elements of the command are doing. Please explain in as simple terminology as possible! I am new to linux commands and I prefer baby lingo to tech lingo at the moment :)
MY RESEARCH: By running man pkill in the linux terminal, a manual appears with the following pkill definition:
signal processs based on their name or other attributes.
which leads me to believe that pkill doesn't only kill a process, but rather can send a lot of different signals, one of which might kill the process. The structure/synopsis of the pkill command was displayed as: pkill [option] pattern
From the list of options in the same manual, -f, -full had the following definition:
The pattern is normally only matched against the process name. When -f is set, the full command line is used.
I didn't completely understand what that meant. Also, there is a -INT before the -f in the command, so that leads me to believe that more than one option can be joined together, however -INT was not displayed in the manual.
The other parts of the command seem to be identifying the program that is running: '^php test_program.php$', but why isn't that part of the command just 'test_program.php'? What does ^php at the beginning and $ and the end do?
You are looking at a Regular Expression. This expression looks for the string test_program.php anywhere in the process name. So if the process name would be something like
/var/php -runcommand test_program.php
it would find the process and kill it.
This also explains the -f, -full option. Not using a Regular Expression, you would have to take the full process name (the preceeding line) to match the process.
Finally, the -INT is usually used to send a runlevel to the task.
EDIT
I was wrong, the -INT option is not used for runlevels (which are for the Linux kernel) but to send signals to a task. This could be something like Term (terminate), Stop (shut down) or Cont (continue process). pkill sends by default the terminate signal to the process.
The /var/php -runcommand test_program.php was an example for a process. If you use the command ps ax, you get a list of all processes and which programs execute them. So I just assumed that the php interpreter resides in /var/php/ and the execution of the php file is a command.
After running into an issue on executing some queries as strings in Java for postgres, I went using string arrays, which solved my existing issues.
After the switch I am now having an issue with pg_dump, but not with pg_restore.
When I supply my method with the following array:
[time, ./pg_dump, -U, lehigh, -d, lehigh, -Fc, data/completedDb.dump]
I get the following error:
pg_dump: too many command-line arguments (first is
"data/completedDb.dump")
ProcessBuilder produces the following for my execution:
time ./pg_dump -U lehigh -d lehigh -Fc data/completedDb.dump
And it works fine when I add the output arrow, and remove the data folder, on the command line.
time ./pg_dump -U lehigh -d lehigh -Fc > completedDb.dump
I'm running this through eclipse, in Java on a postgres database, using :
Runtime.getRuntime().exec();
I've tried using Process.start() but got the same errors, so I'm totally dumbfounded at what I'm doing wrong.
Prior to this change, pg_dump was being executed properly as a single string. I don't want to go back to that method as I want to maintain consistency, but I also want to figure out what I'm doing wrong here.
You should use -f before the output file name, since by default pg_dump outputs to stdout.
Try
[time, ./pg_dump, -U, lehigh, -d, lehigh, -Fc, -f, data/completedDb.dump]
I am trying to execute netstat command from java using runtime execution, but it throwing below IOException.
It works fine for other commands, even the synonym command onetstat is working fine. I am trying understand why netstat alone is failing and how to make it work. any help is appreciated.
java.io.IOException: Cannot run program "netstat": netstat: not found
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1059)
at java.lang.Runtime.exec(Runtime.java:629)
at java.lang.Runtime.exec(Runtime.java:462)
at java.lang.Runtime.exec(Runtime.java:359)
at com.ca.RunCmd.executeCommand(RunCmd.java:30)
at com.ca.RunCmd.main(RunCmd.java:18)
Caused by: java.io.IOException: netstat: not found
at java.lang.UNIXProcess.fullPath(UNIXProcess.java:306)
To really understand what's going on here, you'll need to hunt down the actual executable, whether netstat or onetstat.
If netstat is aliased to onetstat in the shell - depending on which shell you're running, the "whence" or "alias" command will tell you. A simple solution might be to run the command via the shell (/bin/sh -c netstat) rather than running netstat directly.
Another possibility is that these commands are what's known as an "external link"...a way for a UNIX Service pathname to point to a conventional executable in a z/OS dataset. If this is the case, then you very well might have the netstat/onetstat in your path and otherwise correct, but you might not have the correct STEPLIB or LNKLST concatenation. When the system exec's the target (netstat/onetstat), it doesn't find the externally-linked program, and you get the "not found".
All sorts of things can go wrong here, especially when external links are involved. There can be system (APF) authorization issues, missing modules in your STEPLIB/LNKLST, not enough memory to load the program, etc etc etc. Unfortunately UNIX Services on z/OS doesn't always interpret every possible failure code, so sometimes it's necessary to go hunting. A good first start would be to catch the exception you're getting and look for the ERRNO/ERRNO2 values - they can give you a good hint.
If you have traditional z/OS facilities, your friend is the console log...SDSF's Log function or equivalent. There very well might be an x06 abend and a CSV... message on the console that would give you the clues about what to do next.
The solution is to use the actual command instead of the alias command in this case the actual command is onetstat, netstat is an alias command.
The problem is with the alias commands, when you try execute a alias command through the java runtime its failing to execute them. I am yet to find the exact reason but the problem could be replicated easily by the creating an alias for any command try executing them, you can try this in windows environment as well.
I am trying to run the below command from java code using Process process =Runtime.getRuntime().exec(command) but getting the error.
Command: repo forall -c 'pwd;git status'
Error:'pwd;git: -c: line 0: unexpected EOF while looking for matching''`
I am able to run this command from linux terminal but when running from java the problem is with the space after pwd;git. Can anyone help me?
This is an ultra classical mistake and I am frankly surprised that you didn't find the answer to it by searching around.
A Process is not a command interpreter.
However, Runtime.exec() will still try and act as one if you pass it only one argument, and here you'll end up splitting like this:
repo
forall
-c
'pwd;git
status'
Which is obviously not what you want.
Use a ProcessBuilder. I won't do it all for you but here is how to start:
final Process p = new ProcessBuilder()
.command("repo", "forall", "-c", "pwd; git status")
// etc etc
.start();
Link to the javadoc.
I'd like to know how it is started. What is the command to start this java process ? What I mean is I have one running java process, and I'd like to know the command to start it, such as what is the main class and what is the arguments, etc.
Any tool for that ? Thanks
There is a command line tool that comes with the JDK: jps, that will give you the list of java processes being run at the moment you execute the command, the arguments given to the method main and the parameters used for the JVM. Try this:
path\to\jdk\bin\jps -m -l -v
It won't give you the exact command used to start the process, but it will give you a hint of how to "rebuild" that command.
For more info, if you are on a decent distro of linux, try man jps or if you are on Windows, see the Oracle documentation about jps.
Your question wasn't clear. If you are looking to find the command that launched this process than you can look at the property sun.java.command. This will give you the main class name and arguments passed to it. java.class.path property gives you the class path. You can get the arguments passed to the java command itself by using ManagementFactory.getRuntimeMXBean().getInputArguments() method. Using all these you should be able to reconstruct the java command.
If you use Windows, you can use the Taskmanager, go to the Process/Details Tab, where you can see the PID for each Process. There you can add a column for the command line (e.g. in German its "Befehlszeile", i'm not sure how that column is labeled in English).
Then just look at the java.exe/javaw.exe Processes.
You could also use the alternative Taskmanager from Microsoft, Process Explorer, afaik there you can just click right on a process and select details.