diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py
index 371edcadb91c4393893fd14d70f605303a468113..ab426a002bc4d4f12cade883e2df8f08acf1526e 100644
--- a/src/Solver/ASolver.py
+++ b/src/Solver/ASolver.py
@@ -151,7 +151,22 @@ class AbstractSolver(object):
         if self._cmd_input == "":
             return True
 
-        return False
+        cmd = self._cmd_input
+        cmd = cmd.replace("@path", self._path_input)
+        cmd = cmd.replace("@input", self.input_param())
+        cmd = cmd.replace("@dir", self._process.workingDirectory())
+
+        print(f"+ {cmd}")
+
+        cmd = cmd.split()
+        exe = cmd[0]
+        args = cmd[1:]
+
+        self._process.start(
+            exe, args,
+        )
+
+        return True
 
     def run_solver(self):
         if self._cmd_solver == "":
@@ -160,6 +175,9 @@ class AbstractSolver(object):
         cmd = self._cmd_solver
         cmd = cmd.replace("@path", self._path_solver)
         cmd = cmd.replace("@input", self.input_param())
+        cmd = cmd.replace("@dir", self._process.workingDirectory())
+
+        print(f"+ {cmd}")
 
         cmd = cmd.split()
         exe = cmd[0]
@@ -168,8 +186,6 @@ class AbstractSolver(object):
         self._process.start(
             exe, args,
         )
-        self._process.readyRead.connect(self._data_ready)
-        self._process.finished.connect(self._finished)
 
         self._status = STATUS.RUNNING
         return True
@@ -177,8 +193,22 @@ class AbstractSolver(object):
     def run_output_data_fomater(self):
         if self._cmd_output == "":
             return True
+        cmd = self._cmd_output
+        cmd = cmd.replace("@path", self._path_output)
+        cmd = cmd.replace("@input", self.input_param())
+        cmd = cmd.replace("@dir", self._process.workingDirectory())
 
-        return False
+        print(f"+ {cmd}")
+
+        cmd = cmd.split()
+        exe = cmd[0]
+        args = cmd[1:]
+
+        self._process.start(
+            exe, args,
+        )
+
+        return True
 
     def _data_ready(self):
         s = self._process.readAll().data().decode()
@@ -189,15 +219,29 @@ class AbstractSolver(object):
     def _finished(self, exit_code, exit_status):
         if self._output is not None:
             self._output.put(exit_code)
-        self._status = STATUS.STOPED
+
+        if self._step < len(self._runs):
+            self._runs[self._step]()
+            self._step += 1
+        else:
+            self._status = STATUS.STOPED
 
     def run(self, process, output_queue):
         self._process = process
         self._output = output_queue
 
-        if self.run_input_data_fomater():
-            if self.run_solver():
-                return self.run_output_data_fomater()
+        self._process.readyRead.connect(self._data_ready)
+        self._process.finished.connect(self._finished)
+
+        self._step = 0
+        self._runs = [
+            self.run_input_data_fomater,
+            self.run_solver,
+            self.run_output_data_fomater,
+        ]
+
+        self._runs[self._step]()
+        self._step += 1
 
     def kill(self):
         if self._process is None:
@@ -215,11 +259,9 @@ class AbstractSolver(object):
             if self._status == STATUS.PAUSED:
                 os.kill(self._process.pid(), SIGCONT)
                 self._status = STATUS.RUNNING
-            else:
-                self.run_solver()
-        else:
-            self.run_solver()
+                return True
 
+        self.run_solver()
         return True
 
     def pause(self):
@@ -239,12 +281,3 @@ class AbstractSolver(object):
         self._process.terminate()
         self._status = STATUS.STOPED
         return True
-
-
-    def wait(self):
-        if self._process is None:
-            return False
-
-        self._process.wait()
-        self._status = STATUS.STOPED
-        return True
diff --git a/tools/ssh-input.sh b/tools/ssh-input.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7d79cc7daf8270e92cf0de51872bdf2a74f47026
--- /dev/null
+++ b/tools/ssh-input.sh
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+# > ssh-input.sh SERVER DESTDIR
+
+# First argument is the server name/addr
+# The second argument is the destination directory to copy input data
+
+ssh $1 mkdir -p $2
+scp ./* $1:$2
diff --git a/tools/ssh-output.sh b/tools/ssh-output.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f81584a0629bbbbcbfadd80fcd57c4e368f1cdac
--- /dev/null
+++ b/tools/ssh-output.sh
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+# > ssh-output.sh SERVER DESTDIR
+
+# First argument is the server name/addr
+# The second argument is the destination directory to copy input data
+
+scp $1:$2/* ./
diff --git a/tools/ssh-run.sh b/tools/ssh-run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9c59bb9fb828aafde2dc5a345cf05674e009c24d
--- /dev/null
+++ b/tools/ssh-run.sh
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+# > ssh-run.sh SERVER DESTDIR SOLVER INPUT
+
+# First argument is the server name/addr
+# The second argument is the destination directory to copy input data
+# The third argument is the solver path
+# The fourth argument is the input name
+
+ssh $1 "cd $2; $3 $4"