I am developing a network monitoring solution for my Java application so I can sniff packets on my machine interfaces and dump the result in rolling PCAP files. When launching the tcpdump command (using sudo) from the Java code, I get tcpdump: /path/to/app/log/GTP00: Permission denied
DETAILS
The command is executed using Runtime.getRuntime().exec(command) where command is a String valued sudo tcpdump -i eth0 -w /path/to/app/log/GTP -W 50 -C 20 -n net 10.246.212.0/24 and ip
The user launching the Java app is "testUser" which belongs to group "testGroup". This user is allowed to sudo tcpdump.
The destination dir has the following attributes:
[testUser#node ~]$ ls -ld /path/to/app/log
drwxrwxr-x. 2 testUser testGroup 4096 Feb 4 15:40 /path/to/app/log
MORE DETAILS
Launching the command from the command line SUCCESFULLY creates the pcap file in the specified folder.
[testUser#node ~]$ ls -l /path/to/app/log/GTP00
-rw-r--r--. 1 tcpdump tcpdump 1276 Feb 4 16:12 /path/to/app/log/GTP00
I have developed a simplified Java app for testing purposes
package execcommand;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ExecCommand {
public static void main(String[] args) {
try {
String command;
String line;
String iface = "eth0";
String capturePointName = "GTP";
String pcapFilterExpression = "net 10.246.212.0/24 and ip";
int capturePointMaxNumberOfFilesKept = 50;
int capturePointMaxSizeOfFilesInMBytes = 20;
command = "sudo tcpdump -i " + iface + " -w /path/to/app/log/"
+ capturePointName + " -W " + capturePointMaxNumberOfFilesKept + " -C "
+ capturePointMaxSizeOfFilesInMBytes + " -n " + pcapFilterExpression;
Process process = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((line = br.readLine()) != null) {
System.err.println(line);
}
} catch (IOException ex) {
Logger.getLogger(ExecCommand.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
This test program, launched by the same user, SUCCESFULLY creates the pcap file in the specified folder.
[testUser#node ~]$ ls -l /path/to/app/log/GTP00
-rw-r--r--. 1 tcpdump tcpdump 1448 Feb 4 16:21 /path/to/app/log/GTP00
Then, I can infer that the problem is somehow restricted to my Java app. This is how my Java app is launched:
exec java -Dknae_1 -Djavax.net.ssl.trustStorePassword=<trust_pass> -Djavax.net.ssl.trustStore=/path/to/app/etc/certificates/truststore -Djavax.net.ssl.keyStorePassword=<key_store_pass> -Djavax.net.ssl.keyStore=/path/to/app/etc/certificates/keystore -d64 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8887,suspend=y -XX:-UseLargePages -Xss7m -Xmx64m -cp /path/to/app/lib/knae.jar:/path/to/app/lib/xphere_baseentity.jar:/path/to/app/lib/mysql.jar:/path/to/app/lib/log4j-1.2.17.jar:/path/to/app/lib/tools.jar:/path/to/app/conf:/path/to/app/lib/pcap4j-core-1.7.5.jar:/path/to/app/lib/pcap4j-packetfactory-static-1.7.5.jar:/path/to/app/lib/jna-5.1.0.jar:/path/to/app/lib/slf4j-api-1.7.25.jar:/path/to/app/lib/slf4j-simple-1.7.25.jar com.app.package.knae.Knae knae_1
UPDATE
I am able to write the pcap file within /tmp.
I have also tried giving 777 permissions to /path/to/app/log to no avail.
These are the attibutes of both dirs:
[testUser#node ~]$ ls -ld /tmp
drwxrwxrwt. 10 root root 4096 Feb 6 10:13 /tmp
[testUser#node ~]$ ls -ld /path/to/app/log
drwxrwxrwx. 2 testUser testGroup 4096 Feb 6 09:25 /path/to/app/log
I will provide any additional information as needed.
Why is tcpdump complaining about not being able to write this file?
Use absolute paths in command line instead of "sudo" and "tcpdump"
Use ProcessBuilder.class instead of Runtime.exec() because you can specify the working directory, you can use spaces in options and more.
In tcpdump command you have to use -Z flag to specify user because PCAP uses different than caller one. Check this link on ServerFault: tcpdump permisson denied
Related
Cloud Foundry is it possible to copy missing routes from one app to another while doing blue green deployment?
I have an app with few manually added routes, while doing blue green deployment (automated through script) I want to copy missing/manually added routes into new app. Is it possible?
Script:
#!/bin/bash
path="C:/Users/.../Desktop/cf_through_sh/appName.jar"
spaceName="development"
appBlue="appName"
appGreen="${appName}-dev"
manifestFile="C:/Users/.../Desktop/cf_through_sh/manifest-dev.yml"
domains=("domain1.com" "domain2.com")
appHosts=("host-v1" "host-v2")
evaluate_return_code (){
ret=$1
if [[ $ret != 0 ]]
then
exit $ret
fi
}
switch_to_target_space() {
space="development"
echo "Change space to ${space}"
cf t -s ${space}
evaluate_return_code $?
}
push_new_release() {
appGreen=$1
if [ ! -f "${manifestFile}" ]; then
echo "Missing manifest: ${manifestFile}";
exit 1;
fi
if [ ! -f "${path}" ]; then
echo "Missing artifact: ${path}";
exit 1;
fi
echo "Deploying ${path} as ${appGreen}"
cf push ${appGreen} -f ${manifestFile} -p ${path} --no-route
evaluate_return_code $?
}
map_routes() {
app=$1
domains=$2
shift
appHosts=$3
for host in ${appHosts[*]}; do
echo "Mapping ${host} to ${app}"
for domain in ${domains[*]}; do
cf map-route ${app} ${domain} -n ${host}
evaluate_return_code $?
done
done
}
unmap_routes() {
app=$1
domains=$2
shift
appHosts=$3
for host in ${appHosts[*]}; do
echo "Unmapping ${host} from ${app}"
for domain in ${domains[*]}; do
cf unmap-route ${app} ${domain} -n ${host}
evaluate_return_code $?
done
done
}
rename_app() {
oldName=$1
newName=$2
echo "Renaming ${oldName} to ${newName}"
cf rename ${oldName} ${newName}
evaluate_return_code $?
}
switch_names() {
appBlue=$1
appGreen=$2
appTemp="${appBlue}-old"
rename_app ${appBlue} ${appTemp}
rename_app ${appGreen} ${appBlue}
rename_app ${appTemp} ${appGreen}
}
stop_old_release() {
echo "Stopping old ${appGreen} app"
cf stop ${appGreen}
evaluate_return_code $?
}
switch_to_target_space ${spaceName}
push_new_release ${appGreen}
map_routes ${appGreen} ${domains[*]} ${appHosts[*]}
unmap_routes ${appBlue} ${domains[*]} ${appHosts[*]}
switch_names ${appBlue} ${appGreen}
stop_old_release
echo "DONE"
exit 0;
Eg:
appblue has 5 roues
1. host-v1.domain1.com
2. host-v2.domain1.com
3. host-v1.domain2.com
4. host-v2.domain2.com
5. manual-add.domain1.com //manually added route through admin UI
After blue green deployment through script app contains only 4 routes
1. host-v1.domain1.com
2. host-v2.domain1.com
3. host-v1.domain2.com
4. host-v2.domain2.com
How to copy missing 5th route? I don't want to pass host manual-add from script since it's added manually.
In general, is it possible to copy routes from one app to another if not mapped?
This has to be done only through Jenkins (or any CI-CD tool). What we did in our case is, we had a CF-Manifest-Template.yml and CF-Manifest-settings.json and we had a gradle task that would apply the settings from JSON and fill the Manifest-temple and generate a cf-manifest-generated.yml
The gradle file will have a task that would do blue-green-deployment by using this generated manifest file and all the routes will be hard-coded in the manifest-file. This is the standard way of doing it.
But if you want to copy route from an App running in Cloud Foundry and copy thos routes to another-app, then you would need to write a REST Client that connects to Cloud Foundry CloudController and gets all the route of App-A and then creates routes to APP-B
It is pretty simple !!
Write a REST Client that executes this command
cf app APP-A
This will bring back the details of APP-A as a JSON Response. The response would have these parameters
Showing health and status for app APP-A in org Org-A / space DEV as arun2381985#yahoo.com...
name: APP-A
requested state: started
instances: 1/1
usage: 1G x 1 instances
routes: ********
last uploaded: Sat 25 Aug 00:25:45 IST 2018
stack: cflinuxfs2
buildpack: java_buildpack
Read this JSON response and collect the Routes of APP-A and then have that mapped for APP-B .. Its pretty simple
I am trying to write java code to automate the docker commands that I execute. I am actually creating a mssql docker container and then want to restore a DB backup in that container. I am able to achieve this using docker commands but having trouble replicating it using docker-java.
So far I have achieved this:
public static void main(String[] args) throws InterruptedException {
BasicConfigurator.configure();
DockerClient dockerClient
= DockerClientBuilder.getInstance("tcp://localhost:1234").build();
Volume volume1 = new Volume("/var/opt/mssql/backup"); //target
//Network Creation
CreateNetworkResponse networkResponse
= dockerClient.createNetworkCmd()
.withName("java-docker-mssql")
.withDriver("bridge").exec();
//Pulling an image
dockerClient.pullImageCmd("microsoft/mssql-server-linux")
.withTag("latest")
.exec(new PullImageResultCallback())
.awaitCompletion(30, TimeUnit.SECONDS);
//Container Creation
CreateContainerResponse container
= dockerClient.createContainerCmd("microsoft/mssql-server-linux:2017-latest")
.withPortBindings(PortBinding.parse("1433:1433"))
.withEnv("ACCEPT_EULA=Y", "SA_PASSWORD=P#ssw0rd")
.withVolumes(volume1)
.withBinds(new Bind("/Users/robhit_saxena/Downloads/test-bind", volume1)) //is source
.withName("mssql-from-java")
.withNetworkMode("java-docker-mssql")
.exec();
//Starting a container
dockerClient.startContainerCmd(container.getId()).exec();
String containerId = container.getId();
//Executing commands in a running container
ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId())
.withAttachStdout(true)
.withAttachStderr(true)
.withCmd("bash", "-c", "mkdir -p /var/opt/mssql/backup")
.exec();
dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(
new ExecStartResultCallback(System.out, System.err)).awaitCompletion();
ExecCreateCmdResponse execCreateCmdResponse1 = dockerClient.execCreateCmd(container.getId())
.withAttachStdout(true)
.withAttachStderr(true)
.withCmd("bash", "-c", "/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'P#ssw0rd'")
.exec();
dockerClient.execStartCmd(execCreateCmdResponse1.getId()).exec(
new ExecStartResultCallback(System.out, System.err)).awaitCompletion();
}
But, it fails to connect with the following error:
14253 [dockerjava-jaxrs-async-2] DEBUG org.apache.http.wire - http-outgoing-4 << "[0x2][0x0][0x0][0x0][0x0][0x0][0x2][0x5]Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login timeout expired.[\n]"
14253 [dockerjava-jaxrs-async-2] DEBUG org.apache.http.wire - http-outgoing-4 << "Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : TCP Provider: Error code 0x2749.[\n]"
14253 [dockerjava-jaxrs-async-2] DEBUG org.apache.http.wire - http-outgoing-4 << "Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : A network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online..[\n]"
14254 [dockerjava-jaxrs-async-2] DEBUG com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory - 14 * Client response received on thread dockerjava-jaxrs-async-2
Note: When I execute the following command it works:
docker exec -it mssql-from-java /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'P#ssw0rd' -Q 'RESTORE FILELISTONLY FROM DISK = "/var/opt/mssql/backup/BSP-39251DBDump.bak"' | tr -s ' ' | grep ldf | cut -d ' ' -f 1
I have even tried not using the network and excluding the "withNetworkMode" mapping as well while creating the container but nothing works.
Any help would be greatly appreciated!
Thanks!
While trying the new ProcessHandle API in Java 9 on a simple "Dockerized" Java program, I found a difference in terms of behavior when it comes to retrieving process IDs of running processes. Specifically when calling the method ProcessHandle.pid(), the resulting PID on Docker is different than the native ID shown on the host, although the docs say that the method "returns the native process ID of the process". In addition, there was a difference between the results of ProcessHandle.allProcesses().
To demonstrate, the below program does the following:
prints the PID of the current process,
spawns a child process that sleeps for a few seconds (to allow time to print its info),
and finally prints all visible processes.
public static void main(String[] args) {
System.out.println("### Current process info ###");
ProcessHandle currentProcess = ProcessHandle.current();
printInfo(currentProcess);
System.out.println();
// Fork a child process that lasts for a few seconds
spawnProcess("jshell --startup ./sleep.txt");
printAllVisibleProcesses();
}
private static void printAllVisibleProcesses() {
System.out.println("### Visible processes info ###");
ProcessHandle.allProcesses().forEach(ProcessHandleExamples::printInfo);
System.out.println();
}
private static void spawnProcess(String command) {
System.out.println("Spawning: " + command);
try {
Runtime.getRuntime().exec(command);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void printInfo(ProcessHandle processHandle) {
ProcessHandle.Info processInfo = processHandle.info();
System.out.println("Process ID: " + processHandle.pid());
System.out.println("Process arguments: " + Arrays.toString(processInfo.arguments().orElse(new String[0])));
System.out.println("Process executable: " + processInfo.command().orElse(""));
System.out.println("Process command line: " + processInfo.commandLine().orElse(""));
System.out.println("Process start time: " + processInfo.startInstant().orElse(null));
System.out.println("Process total cputime accumulated: " + processInfo.totalCpuDuration().orElse(null));
System.out.println("Process user: " + processInfo.user().orElse(""));
}
When running the application normally (without Docker), the output is as expected; it includes the native PID of the current process, its child process and lots of other visible processes.
### Current process info ###
Process ID: 7756
Process arguments: []
Process executable: D:\Dev\Java\jdk-9\bin\java.exe
Process command line:
Process start time: 2017-10-08T12:23:46.474Z
Process total cputime accumulated: PT0.4368028S
Process user: manouti
Spawning: jshell --startup ./sleep.txt
### Visible processes info ###
... skipping some output
Process ID: 8060
Process arguments: []
Process executable: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
Process command line:
Process start time: 2017-10-08T12:20:04.758Z
Process total cputime accumulated: PT10.4676671S
Process user: manouti
Process ID: 7756
Process arguments: []
Process executable: D:\Dev\Java\jdk-9\bin\java.exe
Process command line:
Process start time: 2017-10-08T12:23:46.474Z
Process total cputime accumulated: PT0.8268053S
Process user: manouti
Process ID: 8080
Process arguments: []
Process executable: D:\Dev\Java\jdk-9\bin\jshell.exe
Process command line:
Process start time: 2017-10-08T12:23:46.992Z
Process total cputime accumulated: PT0.0780005S
Process user: manouti
When I run on Docker (Windows 7 with Docker running on a boot2docker Linux), a much smaller subset of processes are visible, and the PIDs do not match the ones on the host.
$ docker run test/java9-processhandle-example:1.0
After running the above command, the host shows the following processes:
However, the resulting program output below shows PIDs 1 and 16, instead of 4291 and 4333. And the visible processes include the container process and the spawned process.
I'm wondering if this is expected. Since I am relatively new to Docker, if this is a limitation caused by the container, I would be glad if someone could explain it (I'm also not sure if this is reproducible on a different Docker setup, e.g. Docker on Linux or Windows Server). Otherwise, is this a limitation by the API itself when applied in containers (which does not seem to be mentioned anywere in the Javadocs)?
### Current process info ###
Process ID: 1
Process arguments: [ProcessHandleExamples]
Process executable: /usr/lib/jvm/java-9-openjdk-amd64/bin/java
Process command line: /usr/lib/jvm/java-9-openjdk-amd64/bin/java ProcessHandleExamples
Process start time: 2017-10-08T14:17:48.420Z
Process total cputime accumulated: PT0.35S
Process user: root
Spawning: jshell --startup ./sleep.txt
### Visible processes info ###
Process ID: 1
Process arguments: [ProcessHandleExamples]
Process executable: /usr/lib/jvm/java-9-openjdk-amd64/bin/java
Process command line: /usr/lib/jvm/java-9-openjdk-amd64/bin/java ProcessHandleExamples
Process start time: 2017-10-08T14:17:48.420Z
Process total cputime accumulated: PT0.6S
Process user: root
Process ID: 16
Process arguments: [--startup, ./sleep.txt]
Process executable: /usr/lib/jvm/java-9-openjdk-amd64/bin/jshell
Process command line: /usr/lib/jvm/java-9-openjdk-amd64/bin/jshell --startup ./sleep.txt
Process start time: 2017-10-08T14:17:49.070Z
Process total cputime accumulated: PT0.03S
Process user: root
This is nothing specific to Java or Java 9, it's a docker theme.
Each container has its own PID namespace and the first process that is run in the container has a PID of 1.
You can read more about this in the docker documentation, especially:
By default, all containers have the PID namespace enabled.
PID namespace provides separation of processes. The PID Namespace removes the view of the system processes, and allows process ids to be reused including pid 1.
So running a container with --pid=host is needed to allow the ProcessHandle.pid() to return the expected value as implied in the documentation (native PID assigned by operating system).
It also makes the ProcessHandle.allProcesses() return system visible processes, as opposed to just processes bound to the container.
I wrote a small Java command line program to test sending emails from a remote server. I'm getting the dreaded "NoClassDefFoundError" and I can't figure out why.
The server is running:
SunOS 5.10 Generic January 2005
Java 1.5.0_30-b03 ( Sun, standard )
My java program is called
SendEmailACME
The error message is
Exception in thread "main" java.lang.NoClassDefFoundError: javax/activation/DataSource
The complete output from the run of the program is:
bash-3.00$ javac SendEmailACME.java
bash-3.00$ java SendEmailACME
SendEmailACME: Classpath: .:/users/steve/TestProgramsLib/mail.jar:users/steve/TestProgramsLib/activation.jar
DEBUG: setDebug: JavaMail version 1.4.4
Exception in thread "main" java.lang.NoClassDefFoundError: javax/activation/DataSource
at SendEmailACME.main(SendEmailACME.java:47)
bash-3.00$
I ran
java -verbose SendEmailACME
The ouput was too long for stackoverflow. All it included was the regular output, plus a bunch of messages about java loading all of its regular libraries, the libraries from mail.jar, but I didn't see any from javax.activation.*
Output from "$ echo $CLASSPATH" is:
bash-3.00$ echo $CLASSPATH
.:/users/steve/TestProgramsLib/mail.jar:users/steve/TestProgramsLib/activation.jar
bash-3.00$
My home directory is
/users/steve
It contains these two directories
TestPrograms
TestProgramsLib
The first has my program SendEmailACME.java, SendEmailACME.class/
The second has the following jars in it:
bash-3.00$ ls -l
total 1102
-rw-r--r-- 1 steve acme 55932 Apr 19 2006 activation.jar
-rw-r--r-- 1 steve acme 494975 Jan 14 2011 mail.jar
bash-3.00$
This is the source code of my command line program SendEmailACME:
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import java.util.Properties;
public class SendEmailACME {
public static void main(String[] args) throws Exception{
String smtpServer = "msg.abc.acme.com";
int port = 25;
String userid = "acme.staffdirectory";
String password = "password";
String contentType = "text/html";
String subject = "test: Send An Email, From A Java Client Using msg.abc.acme.com";
String from = "ACME.Staff.Directory#acme.com";
String to = "steve#acme.com,joerre123#gmail.com,fake.mail#acme.com,bogus#fauxmail.com";
String body = "<h1>Test. An Email, From A Java Client Using msg.abc.acme.com.</hi>";
System.out.println("SendEmailACME: Classpath: " + System.getProperty("java.class.path"));
Properties props = new Properties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable","true");
props.put("mail.smtp.host", smtpServer);
Session mailSession = Session.getInstance(props);
// Get runtime more runtime output when attempting to send an email
mailSession.setDebug(true);
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, to);
message.setSubject(subject);
message.setContent(body,contentType);
Transport transport = mailSession.getTransport();
transport.connect(smtpServer, port, userid, password);
transport.sendMessage(message,message.getRecipients(Message.RecipientType.TO));
transport.close();
}// end function main()
}// end class SendEmailACME
Here is the output from running a command to see what is inside activation.jar:
bash-3.00$ jar -tf activation.jar
META-INF/MANIFEST.MF
META-INF/SUN_MICR.SF
META-INF/SUN_MICR.RSA
META-INF/
META-INF/mailcap.default
META-INF/mimetypes.default
javax/
javax/activation/
javax/activation/ActivationDataFlavor.class
javax/activation/MimeType.class
javax/activation/MimeTypeParameterList.class
javax/activation/MimeTypeParseException.class
javax/activation/CommandInfo.class
javax/activation/DataHandler$1.class
javax/activation/DataHandler.class
javax/activation/DataSource.class
javax/activation/CommandMap.class
javax/activation/DataContentHandler.class
javax/activation/DataContentHandlerFactory.class
javax/activation/CommandObject.class
javax/activation/DataHandlerDataSource.class
javax/activation/DataSourceDataContentHandler.class
javax/activation/ObjectDataContentHandler.class
javax/activation/FileDataSource.class
javax/activation/FileTypeMap.class
javax/activation/MailcapCommandMap.class
javax/activation/MimetypesFileTypeMap.class
javax/activation/SecuritySupport$1.class
javax/activation/SecuritySupport$2.class
javax/activation/SecuritySupport$3.class
javax/activation/SecuritySupport$4.class
javax/activation/SecuritySupport$5.class
javax/activation/SecuritySupport.class
javax/activation/URLDataSource.class
javax/activation/UnsupportedDataTypeException.class
com/
com/sun/
com/sun/activation/
com/sun/activation/registries/
com/sun/activation/registries/MailcapFile.class
com/sun/activation/registries/MailcapParseException.class
com/sun/activation/registries/MimeTypeFile.class
com/sun/activation/registries/MimeTypeEntry.class
com/sun/activation/registries/LineTokenizer.class
com/sun/activation/registries/LogSupport.class
com/sun/activation/registries/MailcapTokenizer.class
com/sun/activation/viewers/
com/sun/activation/viewers/ImageViewer.class
com/sun/activation/viewers/ImageViewerCanvas.class
com/sun/activation/viewers/TextEditor.class
com/sun/activation/viewers/TextViewer.class
bash-3.00$
Everything compiles fine, but it can't seem to find javax.activation.DataSource despite activation.jar being in the classpath
I do not have access to the jdk_home/jre/lib/ext directory.
I have been attempting to execute SendEmailACME from my directory
/users/steve/TestPrograms
Thanks in advance for any help
Steve
bash-3.00$ echo $CLASSPATH
.:/users/steve/TestProgramsLib/mail.jar:users/steve/TestProgramsLib/activation.jar
You appear to be missing a / between mail.jar: and users/steve. This means java is looking in the wrong place for activation.jar (in ./users rather than /users).
Your CLASSPATH doesn't contain JDK libraries where javax.* libraries are placed.
I have a java socket server I wrote to allow me to keep a web clusters code base in sync. When I run the init.d script from a shell login like so
[root#web11 www]# /etc/init.d/servermngr start
Logout and all will work fine but if the server reboots or I run the init.d using services like so
[root#web11 www]# service servermngr start
Any of the exec() commands passed to the socket server will not get executed on the linux box. I am assuming it has to do with the JVM having no real shell. If I login and run
[root#web11 www]# /etc/init.d/servermngr start
...and logout all runs nice all CVS commands are executed.
Another note when run as a service the socket server responds to status checks so it is running
Here is the init.d script
#!/bin/sh
# chkconfig: 2345 95 1
# description: Starts Daemon Using ServerManager.jar.
#
# Source function library.
. /etc/init.d/functions
start () {
echo -n $"Starting ServerManager: "
# start daemon
cd /www/servermanager/
daemon java -jar ServerManager.jar > /www/logs/ServerManager.log &
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/cups
echo "";
return $RETVAL
}
stop () {
# stop daemon
echo -n $"Stopping $prog: "
kill `ps uax | grep -i "java -jar ServerManager.ja[r]" | head -n 1 | awk '{print $2}'`
RETVAL=$?
echo "";
return $RETVAL
}
restart() {
stop
start
}
case $1 in
start)
start
;;
stop)
stop
;;
*)
echo $"Usage: servermngr {start|stop}"
exit 3
esac
exit $RETVAL
And the Java responsible for actually executing the code:
// Build cmd Array of Strings
String[] cmd = {"/bin/sh", "-c", "cd /www;cvs up -d htdocs/;cvs up -d phpinclude/"};
final Process process;
try {
process = Runtime.getRuntime().exec(cmd);
BufferedReader buf = new BufferedReader(new InputStreamReader(
process.getInputStream()));
// Since this is a CVS UP we return the Response to PHP
if(input.matches(".*(cvs up).*")){
String line1;
out.println("cvsupdate-start");
System.out.println("CVS Update" + input);
while ((line1 = buf.readLine()) != null) {
out.println(line1);
System.out.println("CVS:" + line1);
}
out.println("cvsupdate-end");
}
} catch (IOException ex) {
System.out.println("IOException on Run cmd " + CommandFactory.class.getName() + " " + ex);
Logger.getLogger(CommandFactory.class.getName()).log(Level.SEVERE, null, ex);
}
Thx for any help
What is the command you are trying to run? cd is not a program and if you have ; you have multiple commands. You can only run one program!
Are you starting the process as root? What version of (bash?) is running on the system? You may want to give csh a whirl just to rule out issues with the shell itself. I'd also suggest chaining the commands with '&' instead of ';'. Finally you may find it easier to create a shell script which contains all your commands and is called by your java process. You may also want to investigate nohup and check /etc/security/limits
You might be happier using http://akuma.kohsuke.org/ to help you with this stuff, or at least Apache Commons Exec.
Here is the startup script that fixed my issue if someone runs into an issue
#!/bin/sh
# chkconfig: 2345 95 1
# description: Starts Daemon Using ServerManager.jar.
#
# Source function library.
. /etc/init.d/functions
RETVAL=0
prog="ServerManager"
servermanager="java"
serveroptions=" -jar ServerManager.jar"
pid_file="/var/run/servermanager.pid"
launch_daemon()
{
/bin/sh << EOF
java -Ddaemon.pidfile=$pid_file $serveroptions <&- &
pid=\$!
echo \${pid}
EOF
}
start () {
echo -n $"Starting $prog: "
if [ -e /var/lock/subsys/servermanager ]; then
if [ -e /var/run/servermanager.pid ] && [ -e /proc/`cat /var/run/servermanager.pid` ]; then
echo -n $"cannot start: servermanager is already running.";
failure $"cannot start: servermanager already running.";
echo
return 1
fi
fi
# start daemon
cd /www/voodoo_servermanager/
export CVSROOT=":pserver:cvsd#cvs.zzzzz.yyy:/cvsroot";
daemon "$servermanager $serveroptions > /www/logs/ServerManager.log &"
#daemon_pid=`launch_daemon`
#daemon ${daemon_pid}
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/servermanager && pidof $servermanager > $pid_file
echo "";
return $RETVAL
}
stop () {
# stop daemon
echo -n $"Stopping $prog: "
if [ ! -e /var/lock/subsys/servermanager ]; then
echo -n $"cannot stop ServerManager: ServerManager is not running."
failure $"cannot stop ServerManager: ServerManager is not running."
echo
return 1;
fi
killproc $servermanager
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/servermanager;
return $RETVAL
}
restart() {
stop
start
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
restart
*)
echo $"Usage: servermngr {start|stop|restart}"
RETVAL=1
esac
exit $RETVAL