我正在尝试编写一个程序,首先ssh'es到两个不同的机器,然后对它们执行一些http请求。这意味着为了能够执行我的http请求,应该运行ssh隧道。
我所做的是我有两个线程,每个线程都运行ssh命令到其中一个框:
Thread thread1 = new Thread(new Runnable(){
public void run(){
try{
Process p1 = Runtime.getRuntime().exec("ssh -A -L12345:localhost:54321 firsthost.com");
p1.waitFor();
}catch (Exception e){}
}
}) ;
thread1.start();
Thread thread2 = new Thread(new Runnable(){
public void run(){
try{
Process p2 = Runtime.getRuntime().exec("ssh -A -L12345:localhost:54321 secondhost.com");
p2.waitFor();
}catch (Exception e){}
}
}) ;
thread2.start();
现在的问题是,在启动线程后,它们并不总是立即开始运行,这意味着我将在建立连接之前发送请求。是否有一种简单的方法(不使用锁或互斥锁),我可以确保在线程启动后我只返回主程序? (我当然不想等待它们结束,因为它们永远不会结束。只需运行第一个命令一次:)如果有更好的方法在后台运行进程而不是这两个单独的线程,那也会很棒!)
谢谢!
答案 0 :(得分:1)
尝试添加-f
和-N
标志,以便在设置端口转发后告诉ssh背景。然后你可以在主线程中执行ssh
命令并等待它们退出(即背景本身),然后再继续。
<强>
-f
强>请求ssh在命令执行之前转到后台。如果ssh要求密码或密码短语,但用户希望在后台使用密码或密码短语,这很有用。这意味着
-n
。在远程站点启动X11程序的推荐方法是ssh -f host xterm
。如果ExitOnForwardFailure配置选项设置为“yes”,则以
-f
启动的客户端将等待所有远程端口转发成功建立,然后再将其置于后台。<强>
-N
强>不要执行远程命令。这对于仅转发端口非常有用(仅限协议版本2)。
(很遗憾,我现在无法对此进行测试。如果不起作用,请道歉。)
答案 1 :(得分:0)
首先,JDK5以后不鼓励直接使用线程。精心设计的执行人员将为我们完成工作。如果你有一个较低版本的java或者你想以这种方式做到这一点,那么,这是一个快速的解决方案,
public class Main {
public static void main(String... objs) throws Exception {
final Process1Thread p1Thread = new Process1Thread();
final Process2Thread p2Thread = new Process2Thread();
Thread p1 = new Thread(p1Thread);
Thread p2 = new Thread(p2Thread);
p1.start(); p2.start();
while(true) {
if(p1Thread.isFinishedCommand() && p2Thread.isFinishedCommand()) {
//send commands
System.out.println("sending commands");
break;
}
}
}
interface FinishedCommand {
boolean isFinishedCommand();
}
static class Process1Thread implements Runnable, FinishedCommand {
private boolean finished = false;
@Override
public boolean isFinishedCommand() {
synchronized(this) {
return finished;
}
}
@Override
public void run() {
try {
final Process p2 = Runtime.getRuntime().exec("dir");
synchronized(this) {
finished = true;
}
p2.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
static class Process2Thread implements Runnable, FinishedCommand {
private boolean finished = false;
@Override
public boolean isFinishedCommand() {
synchronized(this) {
return finished;
}
}
@Override
public void run() {
try {
final Process p2 = Runtime.getRuntime().exec("dir");
synchronized(this) {
finished = true;
}
p2.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
此致 Lyju
答案 2 :(得分:-1)
您可以使用thread1.getState()方法获取线程的状态。你可以在thread1.start()之后将它移到RUNNABLE状态。当thread1等待进程完成时,它将处于BLOCKED状态。