2012-06-28 2 views
1

HP-UX 시스템의 콘솔에서 Java 응용 프로그램을 실행 중입니다. 보고서에 몇 가지 보고서를 생성하고 압축 한 다음 이메일로 발송합니다. 이메일을 제외한 모든 것이 작동합니다.쉘 사용자가 호출 한 것처럼 Java의 System.getRuntime(). exec가 작동하지 않습니다.

메일 바이너리를 사용하여 명령 줄에서 메일을 보내고 있습니다. HP-UX이기 때문에 표준 GNU sendmail과는 조금 다릅니다.

내가 메일을 보내는 데 사용하고 코드입니다 :

public static void EmailReports(String[] recipients, String reportArchive, String subject){ 
     SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy"); 
     String today = dateFormat.format(new Date()); 

     File tempEmailFile; 
     BufferedWriter emailWriter; 
     try { 
      tempEmailFile = File.createTempFile("report_email_" + today, "msg"); 
      emailWriter = new BufferedWriter(new FileWriter(tempEmailFile)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.out.println("Failed to send email. Could not create temporary file."); 
      return; 
     } 

     try { 
      emailWriter.write("SUBJECT: " + subject + "\n"); 
      emailWriter.write("FROM: " + FROM + "\n"); 
      emailWriter.write(BODY + "\n"); 
      emailWriter.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.out.println("Failed to send email. Could not write to temporary file."); 
     } 

     //read the archive in 
     try { 
      FileInputStream archiveIS = new FileInputStream(new File(reportArchive)); 
      OutputStream archiveEncoder = MimeUtility.encode(new FileOutputStream(tempEmailFile, true), "uuencode", Zipper.getArchiveName(reportArchive)); 

      //read archive 
      byte[] buffer = new byte[archiveIS.available()]; //these should never be more than a megabyte or two, so storing it in memory is no big deal. 
      archiveIS.read(buffer); 

      //encode archive 
      archiveEncoder.write(buffer); 

      //close both 
      archiveIS.close(); 
      archiveEncoder.close(); 

     } catch (FileNotFoundException e) { 
      System.out.println("Failed to send email. Could not find archive to email."); 
      e.printStackTrace(); 
     } catch (MessagingException e) { 
      System.out.println("Failed to send email. Could not encode archive."); 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.out.println("Failed to send email. Could not encode archive."); 
     } 
     System.out.println("Sending '" + subject + "' email.");  

     try { 
      Process p = Runtime.getRuntime().exec("mail [email protected] < " + tempEmailFile.getAbsolutePath()); 
      System.out.println("mail [email protected] < " + tempEmailFile.getAbsolutePath()); 

      StringBuffer buffer = new StringBuffer(); 
      while(p.getErrorStream().available() > 0){ 
       buffer.append((char) p.getErrorStream().read()); 
      } 

      System.out.println("STDERR: " + buffer.toString()); 

      buffer = new StringBuffer(); 
      while(p.getInputStream().available() > 0){ 
       buffer.append((char) p.getInputStream().read()); 
      } 

      System.out.println("STDOUT: " + buffer.toString()); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.out.println("Failed to send email. Could not get access to the shell."); 
     } 
    } 

내가 프로그램을 실행하고, 이메일을 보낼 때, 나는 빈 이메일, 제목 없음, 아니 몸, 아니 첨부 파일을 얻을 이며 FROM에 지정된 전자 메일 대신 HP-UX 상자의 user @ hostname에 있습니다.

그러나 실행하는 동일한 줄을 실행하면 (exec를 호출 한 후 인쇄 된 명령 참조) 정확한 사용자에게 제목, 본문 및 첨부 파일이 포함 된 올바른 전자 메일이 전송됩니다.

STDOUT과 STDERR은 모두 비어 있습니다. 거의 마치 내가 빈 파일을 보내는 것처럼 보이지만 exec를 호출하기 전에 파일을 인쇄하면 거기에 있습니다.

여기 무슨 일 이니?

편집 : 만든 시도 :은 Ksh를 사용

: STDIN을 사용하여

try { 
     String cmd = "mail [email protected] < " + tempEmailFile.getAbsolutePath();    
     Runtime.getRuntime().exec(new String[] {"/usr/bin/ksh", cmd}); 

    } catch (IOException e) { 
     e.printStackTrace(); 
     System.out.println("Failed to send email. Could not get access to the shell."); 
    } 

:

try { 
     System.out.println("mail [email protected] < " + tempEmailFile.getAbsolutePath()); 

     Process p = Runtime.getRuntime().exec("mail [email protected] "); 

     FileInputStream inFile = new FileInputStream(tempEmailFile); 
     byte[] byteBuffer = new byte[inFile.available()]; 
     inFile.read(byteBuffer); 
     p.getOutputStream().write(byteBuffer); 

     inFile.close(); 
     p.getOutputStream().close(); 

     StringBuffer buffer = new StringBuffer(); 
     while(p.getErrorStream().available() > 0){ 
      buffer.append((char) p.getErrorStream().read()); 
     } 

     System.out.println("STDERR: " + buffer.toString()); 

     buffer = new StringBuffer(); 
     while(p.getInputStream().available() > 0){ 
      buffer.append((char) p.getInputStream().read()); 
     } 

     System.out.println("STDOUT: " + buffer.toString()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     System.out.println("Failed to send email. Could not get access to the shell."); 
    } 

답변

2

난 강력하게 문제가 리디렉션 의심. 이것은 일반적으로 쉘에 의해 처리됩니다 - 여기에는 쉘이 없습니다.

은 어느 당신은 일반적으로 프로세스를 실행하고 프로세스의 표준 입력 스트림을 얻을 자바, 또는 (아마 간단) 실행에서 쓸 필요가 /bin/sh (또는 무엇이든) 리디렉션을 수행하는 쉘을 얻을 수 . 두 줄에

+0

그 중 어떤 것도 작동하지 않았습니다. 빈 이메일도받지 못했습니다. KSH는 사용중인 쉘입니다. – Malfist

+0

@Malfist : 올바르게 완료되면 두 가지 모두 작동 할 것으로 예상됩니다. 쉘을 사용하여 시도한 방법의 예를 사용하여 게시물을 편집하십시오. –

+0

업데이트 됨, 편집을 참조하십시오. – Malfist

1

분할, 그냥 더 나은 가독성을 얻을 수 있습니다 :

 String cmd = "mail [email protected] < " + tempEmailFile.getAbsolutePath() ; 
     Process p = Runtime.getRuntime().exec (cmd); 

"mail [email protected] < " + tempEmailFile.getAbsolutePath()라는 프로그램을 찾습니다. 그것은 리다이렉션을하지 않을 것입니다 - 당신이 직접 프로세스의 출력을 읽어야 만합니다.

더 이상 경로를 조회하지 않으므로 전체 경로/usr/bin/mail 또는 그 경로를 지정해야 할 수도 있습니다.

그리고 명령과 매개 변수를 분리해야합니다. 대신에 문자열 배열을 사용하십시오 : ("/ path/to/prg", "param1", "param2", "foo = bar"); 당신이

String cmd = "/usr/bin/mail [email protected] < " + tempEmailFile.getAbsolutePath() ; 
String cmdarr = new String [] {"/bin/bash", "-c", cmd}; 
Process p = Runtime.getRuntime().exec (cmdarr); 

그것은 자바 자신, 더 간단에서 파일의 리디렉션을 호출보다 짧은하지만 당신은 다른 오류에 재치있는 반응 할 수있는 능력을 잃게 같은 스크립트 프로그램으로 호출하는 경우

당신은, 리디렉션을 사용할 수 있습니다.

+0

HP-UX는 ksh를 사용합니다. 추가 매개 변수를 추가해야합니까? – Malfist

+0

이것은 작동하지 않았다 – Malfist

+0

@ 마샬리스트 : "작동하지 않았다"는 다소 애매합니다. 메일에 절대 경로를 다시 추가하는 것을 잊어 버렸습니다. Updating ... - 최소한 "bash"를 위해 "-c"가 String으로 명령을 전달해야 할 수도 있습니다. ksh 매뉴얼에서 문자열로 스크립트를 사용하여 ksh 바이너리를 호출하는 방법을 참조하십시오. –

2

exec'ing { "ksh", "-c", "mail [email protected] < " + etc } 시도해보십시오.-c 옵션은 쉘에게 다음 인수를 셸 명령으로 구문 분석하여 가능한 리다이렉션 등으로 알려줍니다. -c이 없으면 ksh는 명령 행을 사용하여 수행 할 작업을 결정하는 경험적 방법을 따르며 원하는 방식으로 명령을 실행하지 않을 수 있습니다.

관련 문제