簡體   English   中英

在 cron 下運行時 Java 作業未寫入文件

[英]Java job not writing to file when running under cron

提前道歉,我的 Java 是垃圾。 我已經(從其他人那里)拼湊了一個腳本,該腳本執行一個腳本,將輸出假脫機到一個文本文件,然后我將其發送到另一個系統。 這是 crontab 條目

jcb@LWS-DEV4B:~/bridge/heartbeat$ crontab -l
*/2 * * * * (cd /home/jcb/bridge/heartbeat/; ./hb_execute_bridge_util_mem_usage.sh)
*/5 * * * * (cd /home/jcb/bridge/heartbeat/; ./hb_bridge_status_cron.sh)

當我手動調用 java 程序時,它可以工作。

jcb@LWS-DEV4B:~/bridge/heartbeat$ java -classpath /home/jcb/bridge/heartbeat/ojdbc6.jar:. hb_bridge_util_mem_usage
jcb@LWS-DEV4B:~/bridge/heartbeat$ ls -ltr hb_bridge_util_mem_usage.txt
-rwxr-xr-x 1 jcb jcb 14919 Oct 28 11:55 hb_bridge_util_mem_usage.txt

當我調用調用 java 程序的 shell 腳本時,它可以工作。

jcb@LWS-DEV4B:~/bridge/heartbeat$ ./hb_execute_bridge_util_mem_usage.sh
jcb@LWS-DEV4B:~/bridge/heartbeat$ ls -ltr hb_bridge_util_mem_usage.txt
-rwxr-xr-x 1 jcb jcb 14919 Oct 28 11:59 hb_bridge_util_mem_usage.txt

但是,cronjob 不會假脫機任何輸出。

-rwxr-xr-x 1 jcb jcb       0 Oct 28 11:52 hb_bridge_util_mem_usage.txt

我在論壇中閱讀了一些關於等待進程的內容,我添加了這些內容以查看它是否有所作為。 這是我的shell腳本:

#!/bin/bash
java -classpath /home/jcb/bridge/heartbeat/ojdbc6.jar:. hb_bridge_util_mem_usage

這是我的 java 程序,再次:等待、銷毀、獲取輸入是我后來添加的東西,看看它是否會有所作為:

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class hb_bridge_util_mem_usage {

  public static Connection getConnection() throws Exception {
    String driver = "oracle.jdbc.driver.OracleDriver";
    String url = "jdbc:oracle:thin:@???";
    String username = "???";
    String password = "???";
    Class.forName(driver);
    Connection conn = DriverManager.getConnection(url, username, password);
    return conn;
  }

  public static void main(String[] args)throws Exception {
    String id = "001";
    String fileName = "hb_bridge_util_mem_usage.txt";

    ProcessBuilder processBuilder = new ProcessBuilder();

    processBuilder.command("bash", "-c", "util_mem_usage | tee /home/jcb/bridge/heartbeat/hb_bridge_util_mem_usage.txt");

    Process process = processBuilder.start();
    InputStream in = process.getInputStream();
    InputStream error = process.getErrorStream();
    for (int i = 0; i < error.available(); i++) {
           System.out.println("" + error.read());
         }

    // wait for 10 seconds and then destroy the process
    Thread.sleep(10000);
    process.destroy();

    FileInputStream fis = null;
    PreparedStatement pstmt = null;
    Connection conn = null;
    try {
      conn = getConnection();
      conn.setAutoCommit(false);
      File file = new File(fileName);
      fis = new FileInputStream(file);
      pstmt = conn.prepareStatement("insert into hb_bridge_util_mem_usage(id, fileName, fileBody) values (?, ?, ?)");
      pstmt.setString(1, id);
      pstmt.setString(2, fileName);
      pstmt.setAsciiStream(3, fis, (int) file.length());
      pstmt.executeUpdate();
      conn.commit();
    } catch (Exception e) {
      System.err.println("Error: " + e.getMessage());
      e.printStackTrace();
    } finally {
      pstmt.close();
      fis.close();
      conn.close();
    }
  }

問題與您的java代碼無關; java 不會因為 cron 調用它而“運行不同”。

有兩種可能的解釋:

進程的用戶

進程歸用戶所有。 他們的權限,例如訪問目錄和文件時,由該用戶被允許做什么來控制。 例如,如果您將/home/barry文件夾設置為“用戶可讀/可寫/可見,但其他任何人都可讀/可見”,即如果您在/home目錄中運行ls -la並且您看到:

rwxr-xr-x barry

然后,如果您以 barry 身份登錄並啟動一個嘗試執行的 Java 應用程序:

Files.write("Hello!", Paths.get("/home/barry/test.txt"));

它會正常工作。 但是,如果您然后以用戶jane運行它,它將失敗:該進程與用戶jane具有相同的權限,而用戶jane無權在該文件夾中寫入。

cron 以某個用戶身份運行您的應用程序。 取決於您如何配置 cron。 如果所述用戶無權寫入文件,您有自己的解釋。 簡單的解決方法是,無論您的應用程序在何處嘗試為正在運行它的任何用戶 cron 編寫一個可寫的位置,或者,您將 cron 配置為在不同的用戶下運行這個,或者,您通過su運行命令這讓您可以以不同的用戶身份運行它。 但是,僅當您以root身份調用su本身時,才能使用su以其他用戶身份運行某些內容。

安全說明:在許多配置下,有一個每個用戶的 cron 表(然后這些任務以該用戶身份運行),以及一個全局 crontable 和其中的所有內容都以 root 身份運行 以 root 身份運行應用程序極其危險; 任何問題都可以消滅或接管整個系統。 您不應該以 root 身份運行。 因此,如果這是在全局 cron 表中並且以 root 身份運行,那么您絕對應該執行su 我們可以或多或少地相信su不會搞砸,因為它會以例如barry的權限調用您的java應用程序,至少這樣您就不必再信任java 出於一個簡單的原因,您不應該信任java :java 是一個復雜的可執行文件,可以運行任意代碼。 NASA 是否寫了它並不重要:您不能像極其簡單的su命令一樣信任這種復雜性。

當前工作目錄

我認為cd東西意味着這不可能,但我不能 100% 確定 java 進程的工作目錄最終是你cd到的目錄。 你可能想檢查一下。 例如,通過寫入System.getProperty("user.dir") (這是一個命名相當奇怪的屬性,它為您提供當前工作目錄),或將new File(".").toAbsolutePath()打印到絕對位置,例如/home/foo/test.txt ,其中/home/foo具有rwxrwxrwx權限(通過運行sudo chmod 777 /home/foo ),在將該 foo 目錄rwxrwxrwx於此測試目的之后。

然后讓 cron 做它的事情,您可以使用該文件來跟蹤調試問題時 Java 進程發出的內容。

問題是 Java 無法執行 C 程序“util_mem_usage”,盡管我到處都有“su”命令。 我的解決方案是將這個命令分離到一個 shell scipt 中。 這些路徑是 C 程序運行所需的(可能也是 Java 一直在默默掙扎的東西)。

#!/bin/bash
PATH=/home/jcb/bin:/usr/bin/
**LD_LIBRARY_PATH=/home/jcb/lib
PROJECT_ROOT=/home/jcb
export LD_LIBRARY_PATH
export PROJECT_ROOT**
util_mem_usage | tee /home/jcb/bridge/heartbeat/hb_bridge_util_mem_usage.txt

我的 java 程序然后調用它而不是 C 實用程序

processBuilder.command("bash", "-c", "/home/jcb/bridge/heartbeat/hb_get_bridge_util_mem_usage.sh");

這似乎不是一個優雅的解決方案,但它有效......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM