[英]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.