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