Doubts with command: pkill -INT -f '^php test_program.php$' - java

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.

Related

Java sub-process command line execution with/without cmd.exe

My question consists of several things I don't understand about the use of "cmd.exe", "/c" when executing sub-processes from Java in Windows. Basically, I couldn't find a good explanation about when and why they're needed.
My specific problems: I have a small framework for sub-processes execution. One use is a Java application which "manages" several other JVMs created by ProcessBuilders. One of the key requirements is that when a sub-process is stuck, or the hosting application is terminating, it must be able to kill the sub-processes.
The problem is, on one hand, doing this:
new ProcessBuilder("java", "...").start();
Causes this:
Could not find or load main class ...
As if the system variables or directory are different (which they're not). On the other hand, wrapping it in a cmd.exe like this:
new ProcessBuilder("cmd.exe", "/c", "java", "...").start();
WORKS, but creates another cmd.exe process, which has a side effect: the child JVM is now a sub-sub-process, and process.destroy(); doesn't kill it (a known bug in the Windows JRE as I found).
This specific problem was handled on a different level, since all those applications are ours and we know their PIDs. But it's an example how cmd.exe makes everything work differently (or prevent the JVM from working at all). So I'd like to know what exactly happens there.
Here the framework itself comes into the picture as well. It's also going to be used by our testing platform. I'd like to provide an API which allows wrapping the command with a cmd.exe /c by a parameter. But, what exactly is the meaning of that parameter? How do the users decide if they want a cmd.exe wrapping?
AND a bonus I'd appreciate: is any of this relevant in other OS? Does it have some kind of an equivalent, say, in Linux?
Came across it again and found the problem, and some additional insights.
#HarryJohnston - good point, according to the javadoc the sub-process inherits the environment from both ProcessBuilder and Runtime.getRuntime.exec(...) APIs so it's not the issue (and java.exe is in fact found so PATH is obviously available).
But it seems certain command line features are lost. Among others it's this kind of %VARIABLE% usage in command line - they're not interpreted unless the command starts with cmd.exe /c.
In this case of class not found (it could also cause NoClassDefFoundError), I had several variables used in the classpath (perhaps I should have posted the entire command, but it's kinda long). When I replaced them with the literary paths, everything worked.
Basically:
java -cp %classpath% Main - bad
cmd.exe /c java -cp %classpath% Main - good
java -cp D:\proj\bin Main - good
So, on the general question of how's the behavior different with cmd.exe:
Variable references like this: %VARIABLE% are only interpreted by cmd.exe.
With cmd.exe you don't really need to split the command into String array of parameters, you can use one long String (array of "cmd.exe", "/c", "the rest...").
The sub-process will be cmd.exe and not the actual executable, so process.destroy() won't kill it. This might be a bug fixed in later versions (I used Java 7 and 8, Windows 7 and Server 2012).
File associations only work with cmd.exe, so you can't "execute" a file that is not a program or script ("CreateProcess error=193, %1 is not a valid Win32 application"). Calling executables defined in PATH does work.
start and call are only available under cmd.exe.
Command level errors behave differently as well: With cmd.exe the error will just be in the output stream, whereas without it the API throws an exception, which might also have a slightly different description.
For example:
nothing will cause java.io.IOException: CreateProcess error=2, The system cannot find the file specified
cmd.exe /c nothing will return output: 'nothing' is not recognized as an internal or external command, operable program or batch file, and a return value of 1 (the only indication something went wrong).
On the deeper question of why, and is this the full list of differences, I still don't really know. Looks like the JVM has its way of running commands, which you can "wrap" with cmd.exe for additional features and protection.
Another interesting fact is when you run a Batch, it's actually run under a cmd.exe (with all its features). From my tests it seems process.destroy() can only kill it if it's not waiting for anything external (if stuck on pause for example), with or without additional cmd.exe /c wrapping, but not if it runs a sub-process - which is consistent with the cmd.exe limitation mentioned in point 3.

Starting and killing java app with shell script (Debian)

I'm new to UNIX. I want to start my java app with a script like so:
#!/bin/sh
java -jar /usr/ScriptCheck.jar &
echo $! > /var/run/ScriptCheck.pid
This is supposedly working. It does run the app and it does write the pid file. But when I try to stop the process with a different script which contains this:
#!/bin/sh
kill -9 /var/run/ScriptCheck.pid
the console gives me this error:
bash: kill: /var/run/ScriptCheck.pid: arguments must be process or job IDs
My best guess is that I'm not writing the right code in the stop script, maybe not giving the right command to open the .pid file.
Any help will be very appreciated.
You're passing a file name as an argument to kill when it expects a (proces id) number, so just read the process id from that file and pass it to kill:
#!/bin/sh
PID=$(cat /var/run/ScriptCheck.pid)
kill -9 $PID
A quick and dirty method would be :
kill -9 $(cat /var/run/ScriptCheck.pid)
Your syntax is wrong, kill takes a process id, not a file. You also should not be using kill -9 unless you absolutely know what you are doing.
kill $(cat /var/run/ScriptCheck.pid)
or
xargs kill </var/run/ScriptCheck.pid
I think you need to read in the contents of the ScriptCheck.pid file (which I'm assuming has only one entry with the PID of the process in the first row).
#!/bin/sh
procID=0;
while read line
do
procID="$line";
done </var/run/ScriptCheck.pid
kill -9 procID
I've never had to create my own pid; your question was interesting.
Here is a bash code snippet I found:
#!/bin/bash
PROGRAM=/path/to/myprog
$PROGRAM &
PID=$!
echo $PID > /path/to/pid/file.pid
You would have to have root privileges to put your file.pid into /var/run --referenced by a lot of articles -- which is why daemons have root privileges.
In this case, you need to put your pid some agreed upon place, known to your start and stop scripts. You can use the fact a pid file exists, for example, not to allow a second identical process to run.
The $PROGRAM & puts the script into background "batch" mode.
If you want the program to hang around after your script exits, I suggest launching it with nohup, which means the program won't die, when your script logs out.
I just checked. The PID is returned with a nohup.

SQLCMD not working when run using Java

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.

how to get the process id for a java process at the command line in freeBSD, sh

I need some help writing a command that will be put into a .sh. I want to return the process id, which in the output below is 3678, but I'm having diffuclty because the process id changes everytime it gets restarted, so my code breaks
Output:
[root#server1 /usr/home/aaron]# ps -xauww | grep java | grep www
www 3678 0.0 3.2 1308176 267864 ?? Is 3:21PM 0:17.19 [java]
[root#server1 /usr/home/aaron]#
Heres what I was doing until I realized the column changed when the pid changed:
ps -xauww | grep java | grep www | cut -d" " -f6
Any help is appreciated. thanks.
If the starting is automated by a shell script, you can write the pid of the just-started-process which is in the variable $!.
java ...... &
echo "$!" > myjavaprogram.pid
When you need to kill it, just do:
kill `cat myjavaprogram.pid`
Below pgrep command works for getting pid by jar-file name:
pgrep -f test-app.jar
As per http://cfajohnson.com/shell/cus-faq-2.html
How do I get a process id given a process name? Or, how do I find
out if a process is still running, given a process ID?
There isn't a reliable way to to this portably in the shell. Some
systems reuse process ids much like file descriptors. That is,
they use the lowest numbered pid which is not currently in use
when starting a new process. That means that the pid you're
looking for is there, but might not refer to the process you think
it does.
The usual approach is to parse the output of ps, but that involves
a race condition, since the pid you find that way may not refer to
the same process when you actually do something with that
pid. There's no good way around that in a shell script though, so
be advised that you might be stepping into a trap.
One suggestion is to use pgrep if on Solaris, and 'ps h -o pid -C
$STRING' if not, and your ps supports that syntax, but neither of
those are perfect or ubiquitous.
The normal solution when writing C programs is to create a pid
file, and then lock it with fcntl(2). Then, if another program
wants to know if that program is really running, it can attempt to
gain a lock on the file. If the lock attempt fails, then it knows
the file is still running.
We don't have options in the shell like that, unless we can supply
a C program which can try the lock for the script. Even so, the
race condition described above still exists.
That being said look at this: http://www.faqs.org/faqs/unix-faq/faq/part3/section-10.html it might help you out ?
One way can be found in: man pgrep

What's the easiest in a shell script to ensure its not run as root?

I have a Java application executed from a ([ba]sh) shell script and unfortunately sometimes the people responsible for deploying it and starting it fail to switch to the appropriate user before starting the application. In this situation I'd like the application to not run at the very least, and ideally issue a warning not to do that. I thought about trying to alias java or change the path for root to include a fake java which does so, but this might have undesirable side effects and isn't going to be effective easily since the shell script specifies the full path to the java binary.
So, is there a standard idiom in shell scripts for 'don't run if I'm root'?
Example in bash:
if [ `id -u` = 0 ]; then
echo "You are root, go away!"
exit 1
fi
In BASH, you can take the output of whoami and compare it to root.
I use something like this at the beginning of scripts that I want to
be run under a service account:
LUSER='my-service'
if [ `id -un` != $LUSER ]; then
exec su $LUSER -s $SHELL -c "$0 $#"
fi
# actual script commands here.
If run as the correct user, execution will continue as planned. If run
as root, privileges are dropped to the wanted user-id. Other users
will get a password prompt which should tell them that something is
wrong.
su -s $SHELL ... is used to override the shell set in /etc/passwrd
-- it may be set to /bin/false for the service account.
I have used this on Debian systems, using bash and dash. Feel free
to comment if portability can be improved.

Categories