【发布时间】:2014-05-05 13:31:21
【问题描述】:
我正在尝试通过使用管道调用 SFTP 进程来使用 SFTP 复制文件(在 linux 上)。
我第一次尝试调用“ls”,但我的问题是我不知道命令的输出何时完成,所以我知道我可以发送另一个命令,并检查第一个命令的输出。
我希望 sftp 在命令完成后再次打印出它的提示,如下所示:
sftp>ls
...output...
sftp>
这样我就会知道命令何时完成。然而发生的事情是我只是得到...输出...但我从未收到新的 sftp> 提示。
我不明白这是如何在命令行中工作的,而不是在手动通过管道运行时。 this PHP article 也建议使用这种等待 sftp> 提示符的方法。
我用 java 和 ruby 编写了两个实现,它们都表现出相同的行为。我小心不要使用缓冲阅读器,因为我知道这可能会导致问题,因为 sftp 不会在“sftp>”提示符后放置回车,但无济于事。
如果我在 shell echo ls | sftp <parameters> 中运行,那么它会输出并退出,而不给出新的提示。这对我来说实际上是一种“足够好”的行为。
我知道我可以在一个文件中编写我想要运行的所有命令,并通过命令参数将该文件提供给 sftp,但我发现管道方法比诉诸临时文件更可行且不那么笨重。
这里是 Java 实现:
String[] cmd = new String[]{"sftp", Config.getSshTargetUsername()
+ "@" + Config.getSshTargetHost()};
Process p = Runtime.getRuntime().exec(cmd);
InputStreamReader inp = new InputStreamReader(p.getInputStream());
OutputStreamWriter out = new OutputStreamWriter(p.getOutputStream());
out.write("ls\n");
out.flush();
StringBuilder read = new StringBuilder();
char[] buf = new char[256];
while (true) {
int bytes = inp.read(buf);
read.append(buf, 0, bytes);
System.out.println(read);
System.out.flush();
}
还有红宝石:
require 'open3'
cmd = "sftp #{username}@#{host}"
Open3.popen2e(cmd) do |stdin, stdout_err, wait_thr|
stdin.puts "ls"
while chr = stdout_err.getc
putc chr
end
end
更新:现在我意识到,如果我启动 bash,我会得到完全相同的行为。所以这是关于管道的一般情况,与 sftp 无关。
【问题讨论】:
-
所以如果
echo ls | sftp没问题,那么echo "cd dir1; ls ; cd dir2 ; ls" | sftp有什么问题。嗯..我猜我假设sftp理解由;字符分隔的cmds(不是一个安全的假设;-)..printf "cd dir1 \n ls \n cd dir2 \n ls \n" | sftp怎么样。祝你好运。 -
我尝试发送“ls;再见”,如果应用程序退出,那么我知道命令已完成并且我可以解析,遗憾的是 sftp 然后说“无效命令”。使用回车,它意味着两个命令,但我想在发送第二个命令之前等待第一个命令完成,尽管立即发送两个命令可能工作得很好。如果我不进一步了解其他可能性,我会尽快对其进行测试。