如何编写 Java 程序/Shell 脚本组合,以便可以将 Java 程序作为远程命令调用,同时提供本地文件?

如何编写 Java 程序/Shell 脚本组合,以便可以将 Java 程序作为远程命令调用,同时提供本地文件?

这与如何执行远程命令并传入本地文件作为输入?

我编写了一个简单的 Java 程序来打印文件的第一行 -

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.OutputStreamWriter;

public class ReadFirstLine 
{
    public static void main(String[] args) throws Exception 
    {
       String filename = args[0];

       BufferedReader iR  = new BufferedReader (new FileReader(filename));
       BufferedWriter oW = new BufferedWriter(new OutputStreamWriter(System.out));

       outputWriter.write(iR.readLine());

       iR.close();
       oW.close();
    }
}

然后,我在 /usr/bin 目录中创建了一个名为的符号链接ReadFirstLine,它指向 /usr/local/RFL/ReadFirstLine 脚本 -

#! /bin/bash

java -cp "/usr/local/RFL" ReadFirstLine "$1" 

(/usr/local/RFL 有 ReadFirstLine.class)

现在,我可以从任何目录调用 ReadFirstLine,如下所示 -

$ ReadFirstLine simplefile.txt

我想从不同的机器调用同一个脚本。所以从远程机器我尝试 -

$ ssh username@xyz ReadFirstLine < localfile.txt  

但是,我收到了错误

Exception in thread "main" java.io.FileNotFoundException:  (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:146)
    at java.io.FileInputStream.<init>(FileInputStream.java:101)
    at java.io.FileReader.<init>(FileReader.java:58)
    at ReadFirstLine.main(ReadFirstLine.java:12)

如何修改 Java 程序/脚本以使此远程调用有效?

答案1

我对 Java 一无所知,但我可以向您展示概念证明。说我们有本地文件.txt:

Here is the local file.

在远程机器上,我们有远程.sh:

#!/bin/bash
cat /dev/stdin

请注意,远程计算机上的脚本调用一个程序,该程序读取自 stdin。然后传递内容本地文件.txt到你的 ssh 命令:

user@local:~$ cat localfile.txt | ssh user@remote remote.sh
Here is the local file.

您的 Java 程序正在尝试读取文件远程计算机上不存在该文件。我想你可以尝试模仿本地文件。

改变远程.sh到:

#!/bin/bash
cat "$@"

并调用它

user@local:~$ cat localfile.txt | ssh user@remote 'remote.sh <(cat /dev/stdin)'
Here is the local file.

我认为将 Java 程序中的该部分更改为从stdin.

猜测事情可能会变得混乱如果本地文件.txt包含任何可能被 shell 解释为可扩展的内容(例如*),但这需要您自己弄清楚。

答案2

问题在于 shell 重定向 (<) 通过 ssh 隧道发送文件。 Java 类需要的不是文件,而是带有本地文件“文件名”的字符串,该文件将用 FileReader 读取。

不将文件名传递给 FileReader,而是从标准输入读取。

InputStreamReader isReader = new InputStreamReader(System.in);
BufferedReader iR  = new BufferedReader (isReader);

以此作为参考: https://stackoverflow.com/questions/5724646/how-to-pipe-in​​put-to-java-program-with-bash

现在你的班级将是:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;

public class ReadFirstLine 
{
    public static void main(String[] args) throws Exception 
    {
       String filename = args[0];
       System.out.println(filename);

       //BufferedReader iR  = new BufferedReader (new FileReader(filename));
       InputStreamReader isReader = new InputStreamReader(System.in);
       BufferedReader iR  = new BufferedReader (isReader);

       BufferedWriter oW = new BufferedWriter(new OutputStreamWriter(System.out));

       //outputWriter.write(iR.readLine());
       System.out.println(iR.readLine());

       iR.close();
       oW.close();
    }
}

但对于这个任务我肯定会使用:

head -1 filename.txt

:)

答案3

根据定义,本地文件位于您的本地计算机上。 java 程序位于远程计算机上。远程计算机不知道您的本地文件,并且在任何生产情况下都可能没有读取它的权限。对于这种情况,我可以想到三种一般方法:

1) 将 Java 程序更改为从 stdin 读取而不是从文件读取。然后你当前的语法$ ssh username@xyz ReadFirstLine < localfile.txt就可以工作了。

2) 在运行java程序之前,将文件从本地计算机scp到远程计算机。 scp localfile.txt username@xyz 确保将其放入 java 程序的工作目录中。

3) 将远程计算机中的远程目录挂载到本地计算机。这是最接近您所要求的设置的解决方案。它将允许您在本地更改文件,远程计算机将看到更改。有关安装远程目录的更多信息,请参阅此答案。

https://stackoverflow.com/questions/232269/how-to-mount-a-linux-directory-from-a- Different-pc-to-your-local-linux-pc

java 程序的参数将是路径正如远程计算机上显示的那样

在本地计算机上:/directory/which/has/been/shared/localfile.txt

在远程计算机上:/path/to/mounted/directory/on/remote/host/localfile.txt

$ ssh username@xyz ReadFirstLine < /path/to/mounted/directory/on/remote/host/localfile.txt

答案4

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.OutputStreamWriter;

public class ReadFirstLine 
{
    public static void main(String[] args) throws Exception 
    {
       String filename = args[0];

       BufferedReader iR  = new BufferedReader (new FileReader(filename));
       BufferedWriter oW = new BufferedWriter(new OutputStreamWriter(System.out));

       outputWriter.write(iR.readLine());

       iR.close();
       oW.close();
    }
}

相关内容