c******n 发帖数: 4965 | 1 ur code:
public class MyClass {
public void main(String args[]){
while ( true ) System.out.println();
}
}
let's say u run it like
ssh remote_host " java -cp myjar.jar MyClass "
and then after a while , press Control-C
would the java code still be running on the remote side ?? :)
why??
it turns out to be a very nasty problem covering many aspects of
Signals, shell, and java, and ssh | g*****g 发帖数: 34805 | 2 use nohup before your command if you want it to run in the background.
And even if you don't use it sometimes it runs in background.
I think it depends on the shell.
【在 c******n 的大作中提到】 : ur code: : public class MyClass { : public void main(String args[]){ : while ( true ) System.out.println(); : } : } : let's say u run it like : ssh remote_host " java -cp myjar.jar MyClass " : and then after a while , press Control-C : would the java code still be running on the remote side ?? :)
| c******n 发帖数: 4965 | 3 no I **want** the java code to terminate
in normal cases, if it's a C-built binary exe, or shell( run by bash
anyways ) , the printing code would indeed exit
but java does not.
it all depends on the code's behavior as to printing to a closed
terminal, normally the code should get a SIGPIPE, but java carefully
avoided that so that it never gets a SIGPIPE
we have kind of taken for granted that if u terminate a ssh connection,
all the children should be terminated, but in fact it's more complicated
than that
【在 g*****g 的大作中提到】 : use nohup before your command if you want it to run in the background. : And even if you don't use it sometimes it runs in background. : I think it depends on the shell.
| r*****l 发帖数: 2859 | 4 If you want to make sure that it terminate, you need to send another command
to kill it.
【在 c******n 的大作中提到】 : no I **want** the java code to terminate : in normal cases, if it's a C-built binary exe, or shell( run by bash : anyways ) , the printing code would indeed exit : but java does not. : it all depends on the code's behavior as to printing to a closed : terminal, normally the code should get a SIGPIPE, but java carefully : avoided that so that it never gets a SIGPIPE : we have kind of taken for granted that if u terminate a ssh connection, : all the children should be terminated, but in fact it's more complicated : than that
| c******n 发帖数: 4965 | 5 one colleague replied
using ssh -t ....
would help
here is my reply to him (his approach partially works, but only when you
terminate ssh client by ctrl-C, which is SIGINT, it does not work
when the ssh is run by a daemon like hudson, and terminated with -15 )
######################################
This is a cleaner way than the hack I came up with: I found that “normally
” the remote code terminates because it wants to print to the terminal,
Which is closed after ssh is closed, so the remote code gets itself a
SIGPIPE. Java somehow carefully avoided the SIGPIPE generation OR ignores
sigpipe,
So it never terminates. My hack was to , as soon as the remote shell starts
, I fire off a sub process to continuously spit out something onto the
STDOUT,
So that this subprocess will be given a sigpipe when ssh closes, and that
subprocess (bash process) traps SIGPIPE and in the sig handler, it sends a
kill to the
Pgid, so that all children of the remote shell are killed, including java.
This is a hard kill with -9
Your “-t” approach does work if I do a “ctrl-C” on the client side,
because ssh behavior is to transport the ctrl-C to remote side, which then
pretty much acts like
A normal tty. But in our particular case, the Hudson job sends a “15” to
kill the Hudson process, so ssh still lingers on.
You can test it with following code a.sh
virtual-machine:~$ cat a.sh
rm /tmp/sig
trap "echo HUP >> /tmp/sig " HUP
trap "echo INT >> /tmp/sig " INT
trap "echo ALRM >> /tmp/sig " ALRM
trap "echo PIPE >> /tmp/sig " PIPE
trap "echo POLL >> /tmp/sig " POLL
trap "echo PROF >> /tmp/sig " PROF
trap "echo TERM >> /tmp/sig " TERM
trap "echo USR >> /tmp/sig " USR
trap "echo USR >> /tmp/sig " USR
trap "echo VTALRM >> /tmp/sig " VTALRM
trap "echo STKFLT >> /tmp/sig " STKFLT
trap "echo PWR >> /tmp/sig " PWR
trap "echo WINCH >> /tmp/sig " WINCH
trap "echo CHLD >> /tmp/sig " CHLD
trap "echo URG >> /tmp/sig " URG
trap "echo TSTP >> /tmp/sig " TSTP
trap "echo TTIN >> /tmp/sig " TTIN
trap "echo TTOU >> /tmp/sig " TTOU
trap "echo STOP >> /tmp/sig " STOP
trap "echo CONT >> /tmp/sig " CONT
trap "echo ABRT >> /tmp/sig " ABRT
trap "echo FPE >> /tmp/sig " FPE
trap "echo ILL >> /tmp/sig " ILL
trap "echo QUIT >> /tmp/sig " QUIT
trap "echo SEGV >> /tmp/sig " SEGV
trap "echo TRAP >> /tmp/sig " TRAP
trap "echo SYS >> /tmp/sig " SYS
trap "echo EMT >> /tmp/sig " EMT
trap "echo BUS >> /tmp/sig " BUS
trap "echo XCPU >> /tmp/sig " XCPU
java -cp .:/tmp/tt.jar TestLog4j
TestLog4j code is a simple dead loop that continuously does Log.info(“
something”)
Run command with
Ssh localhost ‘./a.sh’
Then on the client side, kill the ssh process by “kill -15 your_ssh_pid “,
but the remote bash and java is still running
The funny thing that I don’t understand now is, in the above test, after I
killed the ssh client, I DON’T see the /tmp/sig being generated,
But after I manually kill the java process, and the remote bash terminates,
I can see /tmp/sig being generated, containing the content:
HUP
CONT
This confirms my understanding that a terminated ssh –t would give the
remote side a HUP, but why is the signal cached so long ??? and why is there
a CONT ???
Or does the HUP have nothing to do with ssh ? maybe when the remote bash
terminates, it wants to use the terminal, and only now does it gets a HUP
from the OS ???
【在 g*****g 的大作中提到】 : use nohup before your command if you want it to run in the background. : And even if you don't use it sometimes it runs in background. : I think it depends on the shell.
| c******n 发帖数: 4965 | 6 one colleague replied
using ssh -t ....
would help
here is my reply to him (his approach partially works, but only when you
terminate ssh client by ctrl-C, which is SIGINT, it does not work
when the ssh is run by a daemon like hudson, and terminated with -15 )
######################################
This is a cleaner way than the hack I came up with: I found that “normally
” the remote code terminates because it wants to print to the terminal,
Which is closed after ssh is closed, so the remote code gets itself a
SIGPIPE. Java somehow carefully avoided the SIGPIPE generation OR ignores
sigpipe,
So it never terminates. My hack was to , as soon as the remote shell starts
, I fire off a sub process to continuously spit out something onto the
STDOUT,
So that this subprocess will be given a sigpipe when ssh closes, and that
subprocess (bash process) traps SIGPIPE and in the sig handler, it sends a
kill to the
Pgid, so that all children of the remote shell are killed, including java.
This is a hard kill with -9
Your “-t” approach does work if I do a “ctrl-C” on the client side,
because ssh behavior is to transport the ctrl-C to remote side, which then
pretty much acts like
A normal tty. But in our particular case, the Hudson job sends a “15” to
kill the Hudson process, so ssh still lingers on.
You can test it with following code a.sh
virtual-machine:~$ cat a.sh
rm /tmp/sig
trap "echo HUP >> /tmp/sig " HUP
trap "echo INT >> /tmp/sig " INT
trap "echo ALRM >> /tmp/sig " ALRM
trap "echo PIPE >> /tmp/sig " PIPE
trap "echo POLL >> /tmp/sig " POLL
trap "echo PROF >> /tmp/sig " PROF
trap "echo TERM >> /tmp/sig " TERM
trap "echo USR >> /tmp/sig " USR
trap "echo USR >> /tmp/sig " USR
trap "echo VTALRM >> /tmp/sig " VTALRM
trap "echo STKFLT >> /tmp/sig " STKFLT
trap "echo PWR >> /tmp/sig " PWR
trap "echo WINCH >> /tmp/sig " WINCH
trap "echo CHLD >> /tmp/sig " CHLD
trap "echo URG >> /tmp/sig " URG
trap "echo TSTP >> /tmp/sig " TSTP
trap "echo TTIN >> /tmp/sig " TTIN
trap "echo TTOU >> /tmp/sig " TTOU
trap "echo STOP >> /tmp/sig " STOP
trap "echo CONT >> /tmp/sig " CONT
trap "echo ABRT >> /tmp/sig " ABRT
trap "echo FPE >> /tmp/sig " FPE
trap "echo ILL >> /tmp/sig " ILL
trap "echo QUIT >> /tmp/sig " QUIT
trap "echo SEGV >> /tmp/sig " SEGV
trap "echo TRAP >> /tmp/sig " TRAP
trap "echo SYS >> /tmp/sig " SYS
trap "echo EMT >> /tmp/sig " EMT
trap "echo BUS >> /tmp/sig " BUS
trap "echo XCPU >> /tmp/sig " XCPU
java -cp .:/tmp/tt.jar TestLog4j
TestLog4j code is a simple dead loop that continuously does Log.info(“
something”)
Run command with
Ssh localhost ‘./a.sh’
Then on the client side, kill the ssh process by “kill -15 your_ssh_pid “,
but the remote bash and java is still running
The funny thing that I don’t understand now is, in the above test, after I
killed the ssh client, I DON’T see the /tmp/sig being generated,
But after I manually kill the java process, and the remote bash terminates,
I can see /tmp/sig being generated, containing the content:
HUP
CONT
This confirms my understanding that a terminated ssh –t would give the
remote side a HUP, but why is the signal cached so long ??? and why is there
a CONT ???
Or does the HUP have nothing to do with ssh ? maybe when the remote bash
terminates, it wants to use the terminal, and only now does it gets a HUP
from the OS ???
【在 g*****g 的大作中提到】 : use nohup before your command if you want it to run in the background. : And even if you don't use it sometimes it runs in background. : I think it depends on the shell.
| g*****g 发帖数: 34805 | 7 Well, I think the common practice in industry is to have
a start script and a stop script, and you just call them.
That has been working fine for me. You may be looking
for solution in the hard way.
normally
【在 c******n 的大作中提到】 : one colleague replied : using ssh -t .... : would help : here is my reply to him (his approach partially works, but only when you : terminate ssh client by ctrl-C, which is SIGINT, it does not work : when the ssh is run by a daemon like hudson, and terminated with -15 ) : ###################################### : This is a cleaner way than the hack I came up with: I found that “normally : ” the remote code terminates because it wants to print to the terminal, : Which is closed after ssh is closed, so the remote code gets itself a
| r*****l 发帖数: 2859 | 8 Agree.
That's why I mentioned before: If you want to make sure that it terminate,
you need to send another command to kill it.
【在 g*****g 的大作中提到】 : Well, I think the common practice in industry is to have : a start script and a stop script, and you just call them. : That has been working fine for me. You may be looking : for solution in the hard way. : : normally
| c******n 发帖数: 4965 | 9 problem is , this is the exception termination case (user pressess "cancel
job" on hudson)
your only way is to catch the signal, cuz there is no chance to run any code
after the "cancel job" kills the top level hudson process
but I guess having a single catcher on the hudson process is cleaner,
sending SIGINT to all ssh -t processes
【在 g*****g 的大作中提到】 : Well, I think the common practice in industry is to have : a start script and a stop script, and you just call them. : That has been working fine for me. You may be looking : for solution in the hard way. : : normally
|
|