Como escrever uma combinação Java Program / Shell Script de forma que você possa chamar o programa Java como um comando remoto e ainda fornecer um arquivo local?

0

Isso está relacionado a Como executar um comando remoto e passar no arquivo local como entrada?

Eu escrevi um programa Java simples que imprime a primeira linha de um arquivo -

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();
    }
}

Em seguida, criei um link simbólico no diretório / usr / bin chamado ReadFirstLine , que aponta para o script / usr / local / RFL / ReadFirstLine -

#! /bin/bash

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

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

Agora, posso chamar o ReadFirstLine de qualquer diretório como este -

$ ReadFirstLine simplefile.txt

Este mesmo script que eu quero chamar de uma máquina diferente. Então, da máquina remota eu tentei -

$ ssh username@xyz ReadFirstLine < localfile.txt  

No entanto, recebi o erro

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)

Como posso modificar o programa Java / script de forma que essa chamada remota funcione?

    
por Wes 10.04.2014 / 00:22

4 respostas

3

Eu não sei nada sobre Java, mas posso mostrar uma prova de conceito. Digamos que temos localfile.txt :

Here is the local file.

e na máquina remota, temos remote.sh :

#!/bin/bash
cat /dev/stdin

Observe que o script na máquina remota chama um programa que lê de stdin . Em seguida, passe o conteúdo de localfile.txt para o seu comando ssh:

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

Seu programa em Java está tentando ler um arquivo que não existe na máquina remota. Eu acho que você poderia tentar imitar um arquivo local.

Mude remote.sh para:

#!/bin/bash
cat "$@"

e invoque-o com

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

Acho que seria mais fácil alterar essa parte do seu programa em Java para ler stdin .

Eu acho que as coisas podem ficar confusas se localfile.txt contiver algo que possa ser interpretado pelo shell como expansível (como * ), mas isso é para você para descobrir.

    
por 14.04.2014 / 19:42
2

O problema é que o redirecionamento do shell (<) envia o arquivo pelo túnel ssh. E a classe Java está esperando não o arquivo, mas uma string com o "nome do arquivo" de um arquivo local que será lido com um FileReader.

Em vez de passar o nome do arquivo para o FileReader, leia a entrada padrão.

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

Usado como referência: link

Agora sua turma será:

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();
    }
}

Mas, para essa tarefa, eu usaria definitivamente:

head -1 filename.txt

:)

    
por 14.04.2014 / 20:34
0

O arquivo local, por definição, está na sua máquina local. O programa java está em uma máquina remota. A máquina remota não sabe sobre o seu arquivo local e, em qualquer situação de produção, provavelmente não tem permissão para lê-lo. Eu posso pensar em três abordagens gerais para esta situação:

1) Altere seu programa Java para ler stdin em vez de um arquivo. Então sua sintaxe atual $ ssh username@xyz ReadFirstLine < localfile.txt funcionará.

2) scp seu arquivo da máquina local para a máquina remota antes de executar o programa java.     scp localfile.txt username @ xyz Certifique-se de colocá-lo no diretório que será o diretório de trabalho do seu programa java.

3) Monte um diretório remoto em sua máquina remota para sua máquina local. Isso tem mais configuração, mas é a solução que mais se aproxima do que você está pedindo. Ele permitirá que você faça alterações no arquivo localmente e a máquina remota verá as alterações. Veja esta resposta para mais sobre a montagem de um direcotry remoto.

link

O argumante para o programa java será o caminho como aparece na máquina remota .

Na máquina local: /directory/which/has/been/shared/localfile.txt

Na máquina remota: /path/to/mounted/directory/on/remote/host/localfile.txt

$ ssh username@xyz ReadFirstLine < /path/to/mounted/directory/on/remote/host/localfile.txt
    
por 14.04.2014 / 20:33
0
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();
    }
}
    
por 28.12.2015 / 10:13