I need that all server console output will appear in client output.
I'm invoking remote method on remote VM, during remote method execution i have some log4j report to the console (on remote).
I want to get/ return all log4j report to my client side console.
is this possible?
Not really. You have to understand that client and server only communicate through that RMI interface that you defined. Then both programs run in their own JVM; so stdout is something completely different for client and server. Same is of course true for any kind of logging infrastructure.
If you really want to push the server messages into your client logs; then you need to enhance that RMI interface, for example by allow the server to send back a List<String> that contains all the messages.
But please note: that is a rather bad design idea. You really do not want that your client logs contain server details. What happens on the server ... stays on the server. Your clients have no business knowing about such details. Because your users might find it very helpful when planning to attack your server ... to know what that thing is doing in detail!
Update: given your input, I would go for the following::
Make sure that you can really capture any char printed to stdout/stderr on your server; for example by "replacing" stdout/stderr so that anything printed there goes in some file (see here). Alternatively, if your VM is Linux, you can make sure both get piped into files.
Instead of trying to capture stuff within your RMI service, I would go for a simpler solution - by adding a RMI interface that allows you to pull those stdout/stderr files from your server. In other words: keep your current RMI calls as they are; but built another service that you can use to retrieve full log files at arbitrary points in time.
Related
I premise that I don't know a lot about DataStage.
I just know that somebody else has created an "ETL job" and I need to launch it from my Java program, that acts as a client.
How should I do?
Edit:
The DataStage server is phisically different from the client where the Java program runs. I am not allowed running commans on the DataStage server. I need to connect via network. I imagined that DataStage provides some kind of network protocol, or webservice, or something so.
You can use the dsjob command - details see the Knowledge Center
Edit:
dsjob needs to be executed at the server.
You could use a insert into a database table from remote and trigger something (i.e. a UDF) that executes the dsjob on the server.
Alternatively use the WaitForFile stage and transfera file to the server.
I have a requirements whereby when the client connects to the server, the server has to find out if the client is running with -javaagent: or not ? Both server and client is written in java . Is there a way the server can get hold of java options that the client is running with ?
On the client, you could use RuntimeMXBean to get the JVM arguments. I'm hoping the -javaagent parameter will also be exposed there.See how-to-get-vm-arguments-from-inside-of-java-application for an example.
The server can find out by the client telling it, like anything else the server wants to know about the client that isn't implied by the connection (e.g. you know the remote address of a TCP client, there's no point in the client sending it over the connection). Sending the client's JVM arguments to the server is unadvisable tight coupling, however. If the server behaves differently based on the client's JVM arguments, then anytime the JVM arguments change the server will have to be updated to handle them. Instead, factor out the varying behavior into a flag that the client sends the server. For HTTP this could be a query param, for RMI a method param, for a roll-your-own protocol...well, you get to roll your own.
Use this API System.getProperty(PropertyName) to check the property name. It could use to find JVM arguments also. If its returns value then what you expect could be achieved.
I have no prior experience with Java and I'm trying to debug a Java class. The class gets called from C++ code. The Java code is full of SysLog calls that would be very helpful to me, but I can't figure out where the output goes, if anywhere.
SysLog is initialized quite simply like this:
public static void initLogger() {
if (log == null) {
log = new Syslog();
}
}
And just to complicate matters, this code is running as a Windows service which means it cannot display any sort of UI, not even console output. The logging must go to a file to be useful.
Do I need to do something to enable the logging? If so, what?
Do I need to do something to send the logging to file(s)? If so, what?
Some info about Syslog - it was originally developed as a generic UNIX logging service. It can log local messages from the system or collect log messages from a number of different servers on the network. Generally any UNIX system will have some implementation of a syslog service available on it. It is a common way of aggregating messages from a number of systems.
On windows, there are a number of syslog server implementations out there. If a syslog service is running on your windows box, then the message might be ending up there.
However, the real question is: to which syslog services does your java app send messages? In theory you could configure your java app to send syslog messages to a remote machine. Or it could try to send messages to the local host (since the syslog listens on a default port).
So I think what VD is saying is to check your java application settings and look for syslog configuration settings. You will have to gain access to a syslog server (either install one locally on windows or get a remote machine to listen). And then using this link configure your java app appropriately.
An additional complication might be that your java environment uses a custom or special sysloghandler. The log4j is very common and is probably the default, but you might want to check that as well.
I have an application where the user (client #1) enters a local ip and a port and the application sends a picture to client #2 (who is also using the same application). However for the final application, I do not want the user to enter the local ip because they will not know this information, and I want my program to automatically figure this out.
My first idea:
Originally, I thought that I could scan all the local ip's for an open port, but this would take way too long.
My second idea:
My next idea was to have the clients send their local hostnames to a remote server which then swaps them and sends them back to the clients.
However, I do not want to run a dedicated server for my second idea.
Because this is more of a design question, I am not including any code but I will do so if necessary.
Do you guys have any ideas on how I should design my application to automatically figure out the local ips?
I did try to google this but couldn't figure out a solution, and so I gave up after an hour and just put my question here.
you can use something like jgroups (allowing discovery based on multicast [lan] etc) or some peer-to-peer implementatons for that, although the latter require at least some servers for initial discovery.
in principle that works the way, that the clients send a message out to "the world" using some well known address and wait for someone to answer. each client itself waits meanwhile for such a message and replies it with information how to "connect" to the current client. This can be done via a so called blackboard, where this bb is either a special tcp-address for multicast-messages (the os/tcp sends the message to all clients listening concurrently) or one or more servers (seeds) that take and coordinate the request and the "membership" lists. anyway, there are some tools ;)
We have some applications that sometimes get into a bad state, but only in production (of course!). While taking a heap dump can help to gather state information, it's often easier to use a remote debugger. Setting this up is easy -- one need only add this to his command line:
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=PORT
There seems to be no available security mechanism, so turning on debugging in production would effectively allow arbitrary code execution (via hotswap).
We have a mix of 1.4.2 and 1.5 Sun JVMs running on Solaris 9 and Linux (Redhat Enterprise 4). How can we enable secure debugging? Any other ways to achieve our goal of production server inspection?
Update: For JDK 1.5+ JVMs, one can specify an interface and port to which the debugger should bind. So, KarlP's suggestion of binding to loopback and just using a SSH tunnel to a local developer box should work given SSH is set up properly on the servers.
However, it seems that JDK1.4x does not allow an interface to be specified for the debug port. So, we can either block access to the debug port somewhere in the network or do some system-specific blocking in the OS itself (IPChains as Jared suggested, etc.)?
Update #2: This is a hack that will let us limit our risk, even on 1.4.2 JVMs:
Command line params:
-Xdebug
-Xrunjdwp:
transport=dt_socket,
server=y,
suspend=n,
address=9001,
onthrow=com.whatever.TurnOnDebuggerException,
launch=nothing
Java Code to turn on debugger:
try {
throw new TurnOnDebuggerException();
} catch (TurnOnDebugger td) {
//Nothing
}
TurnOnDebuggerException can be any exception guaranteed not to be thrown anywhere else.
I tested this on a Windows box to prove that (1) the debugger port does not receive connections initially, and (2) throwing the TurnOnDebugger exception as shown above causes the debugger to come alive. The launch parameter was required (at least on JDK1.4.2), but a garbage value was handled gracefully by the JVM.
We're planning on making a small servlet that, behind appropriate security, can allow us to turn on the debugger. Of course, one can't turn it off afterward, and the debugger still listens promiscuously once its on. But, these are limitations we're willing to accept as debugging of a production system will always result in a restart afterward.
Update #3: I ended up writing three classes: (1) TurnOnDebuggerException, a plain 'ol Java exception, (2) DebuggerPoller, a background thread the checks for the existence of a specified file on the filesystem, and (3) DebuggerMainWrapper, a class that kicks off the polling thread and then reflectively calls the main method of another specified class.
This is how its used:
Replace your "main" class with DebuggerMainWrapper in your start-up scripts
Add two system (-D) params, one specifying the real main class, and the other specifying a file on the filesystem.
Configure the debugger on the command line with the onthrow=com.whatever.TurnOnDebuggerException part added
Add a jar with the three classes mentioned above to the classpath.
Now, when you start up your JVM everything is the same except that a background poller thread is started. Presuming that the file (ours is called TurnOnDebugger) doesn't initially exist, the poller checks for it every N seconds. When the poller first notices it, it throws and immediately catches the TurnOnDebuggerException. Then, the agent is kicked off.
You can't turn it back off, and the machine is not terribly secure when its on. On the upside, I don't think the debugger allows for multiple simultaneous connections, so maintaining a debugging connection is your best defense. We chose the file notification method because it allowed us to piggyback off of our existing Unix authen/author by specifying the trigger file in a directory where only the proper uses have rights. You could easily build a little war file that achieved the same purpose via a socket connection. Of course, since we can't turn off the debugger, we'll only use it to gather data before killing off a sick application. If anyone wants this code, please let me know. However, it will only take you a few minutes to throw it together yourself.
If you use SSH you can allow tunneling and tunnel a port to your local host. No development required, all done using sshd, ssh and/or putty.
The debug socket on your java server can be set up on the local interface 127.0.0.1.
You're absolutely right: the Java Debugging API is inherently insecure. You can, however, limit it to UNIX domain sockets, and write a proxy with SSL/SSH to let you have authenticated and encrypted external connections that are then proxied into the UNIX domain socket. That at least reduces your exposure to someone who can get a process into the server, or someone who can crack your SSL.
Export information/services into JMX and then use RMI+SSL to access it remotely. Your situation is what JMX is designed for (the M stands for Management).
Good question.
I'm not aware of any built-in ability to encrypt connections to the debugging port.
There may be a much better/easier solution, but I would do the following:
Put the production machine behind a firewall that blocks access to the debugging port(s).
Run a proxy process on the host itself that connects to the port, and encrypts the input and output from the socket.
Run a proxy client on the debugging workstation that also encrypts/decrypts the input. Have this connect to the server proxy. Communication between them would be encrypted.
Connect your debugger to the proxy client.