- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Java 程序,我正在其中触发 shell 脚本。Java 代码示例是:
ProcessBuilder pb = new ProcessBuilder(cmdList);
p = pb.start();
p.waitFor();
其中 cmdList 包含执行 shell 所需的所有必要输入参数。该 shell 脚本内部有一个 for 循环,并在该循环中执行一些数据库脚本,并在文件中打印结果信息和错误日志。
下面是示例 shell 脚本代码:
#!/bin/bash
导出 PATH=/apps/PostgresPlus/as9.6/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
设置-eE
#################################################### ## 开始TIME_ELAPSED=""TIME_ELAPSED_IN_HOURS=""SCRIPT_START_TIME_FORMATTED=日期 '+%F %T'
SCRIPT_START_TIME_IN_SEC=日期 +%s
PROCESS_LOG_BASE_PATH="/data/logs/purge_log/"PROCESS_LOG="$PROCESS_LOG_BASE_PATH/purge.log"
陷阱'err=$?; logError 2>&1“清除期间发生错误。在 $LINENO: ${BASH_COMMAND} 行处退出,状态为 $err。请检查日志以获取更多信息。” >>$PROCESS_LOG'错误trap 'logError 2>&1“清除期间发生错误。由于收到外部中断而退出 shell 脚本执行。请检查日志以获取更多信息。” >>$PROCESS_LOG;陷阱 ERR' INT
横幅(){ echo “+------------------------------------------------------------ --------------------------------------------------+ ” printf "|tput 粗体
[ %-40s tput sgr0
|\n""$1 ] tput setaf 2
$2" echo “+------------------------------------------------------------ --------------------------------------------------+ ”}
日志错误(){ printf "[ProcessId- $$] [日期 "+%Y-%m-%d %H:%M:%S"
] tput setaf 1 tput 粗体
[错误] tput setaf 1
%-40s tput sgr0
\n""$@"}
日志信息(){ printf "[ProcessId- $$] [date "+%Y-%m-%d %H:%M:%S"
] tput setaf 6 粗体
[INFO ] %-40s tput sgr0
\n""$@"}日志警告(){ printf "[ProcessId- $$] [date "+%Y-%m-%d %H:%M:%S"
] tput setaf 3
tput 粗体
[警告] %-40s tput sgr0
\n""$@"}
logHint(){ printf "[ProcessId- $$] [date "+%Y-%m-%d %H:%M:%S"
] tput setaf 5
tput satm
%-40s tput sgr0
\n""$@"}
主函数(){
横幅“$SCRIPT_START_TIME_FORMATTED”“已开始处理”|三通-a $PROCESS_LOG logInfo "在 $SCRIPT_START_TIME_FORMATTED 开始执行"|三通-a $PROCESS_LOG
set PGPASSWORD=$DB_PASSWORD
export PGPASSWORD=$DB_PASSWORD
# Call DB function for audit and category wise data purging, population of schema names
SCHEMA_NAMES_RESULT=$(psql -h $HOST_NAME -d $DB_NAME -U $DB_USER -p $DB_PORT -At -c "SELECT $COMMON_SCHEMA_NAME.purge_audit_and_populate_schema_names('$COMMON_SCHEMA_NAME', $PURGE_DATA_INTERVAL_IN_DAYS,'$SCHEMA_NAMES',$NUM_TOP_CONTRIBUTING_TENANTS)")
SCHEMA_NAMES_RESULT=$(echo "$SCHEMA_NAMES_RESULT" | sed 's/{//g; s/}//g; s/"//g' )
SCHEMA_NAMES=$(echo $SCHEMA_NAMES_RESULT | rev | cut -d"," -f2- | rev)
#Convert comma separated string of tenants to array
SCHEMA_NAMES=($(echo "$SCHEMA_NAMES" | tr ',' '\n'))
# loop for multi schema
for element in "${SCHEMA_NAMES[@]}"
do
logInfo "Effective tenant - $element, Script start time - $SCRIPT_START_TIME_FORMATTED" | tee -a $PROCESS_LOG
# PGSQL call to DB function to execute purging
logInfo "Time elapsed since script execution started - $TIME_ELAPSED" | tee -a $PROCESS_LOG
done
#logInfo "Purge completed!" | tee -a $PROCESS_LOG
logInfo "Purge execution completed successfully at `date '+%F %T'`" | tee -a $PROCESS_LOG
exit 0
}
mkdir -p $PROCESS_LOG_BASE_PATH主要“$@”
#################################################### ## 结尾以下是我对该程序的观察。
当通过上述 java 程序触发 shell 脚本时,我观察到以下行为。
a.它在 for 循环中进行一定的迭代后挂起。
b.随着我减少 shell 脚本中的日志条目数量,迭代(for 循环)数量不断增加。
c.当我删除所有信息日志并继续仅打印错误日志时,它成功完成。
有人可以帮助确定此行为背后的原因吗?
目前,我检查了 for 循环中的迭代次数,但是当我开始接收多个错误日志时,该问题可能随时发生。
问候
库沙格拉
最佳答案
您必须使用流程流或映射 err和 out文件,以便 native 缓冲区不会填满。如果您创建线程来使用每个流,效果会更好。 hacky 单线程版本是这样的:
ProcessBuilder pb = new ProcessBuilder(cmdList);
p = pb.start();
try (InputStream in = p.getInputStream();
InputStream err = p.getErrorStream();
OutputStream closeOnly = p.getOutputStream()) {
while (p.isAlive()) {
long skipped = 0L;
try {
skipped = in.skip(in.available())
+ err.skip(err.available());
} catch (IOException jdk8155808) {
byte[] b = new byte[2048];
int read = in.read(b, 0, Math.min(b.length, in.available());
if (read > 0) {
skipped += read;
}
read = err.read(b, 0, Math.min(b.length, err.available());
if (read > 0) {
skipped += read;
}
}
if(skipped == 0L) {
p.waitFor(5L, TimeUnit.MILLISECONDS);
}
}
} finally {
p.destroy();
}
线程方式的工作原理如下:
public void foo() {
class DevNull implements Runnable {
private final InputStream is;
DevNull(final InputStream is) {
is = Objects.requireNonNull(is);
}
public void run() {
byte[] b = new byte[64];
try {
while (is.read(b) >= 0);
} catch(IOException ignore) {
}
}
}
ExecutorService e = Executors.newCachedThreadPool();
ProcessBuilder pb = new ProcessBuilder(cmdList);
Process p = pb.start();
try (InputStream in = p.getInputStream();
InputStream err = p.getErrorStream();
OutputStream closeOnly = p.getOutputStream()) {
e.execute(new DevNull(in));
e.execute(new DevNull(err));
p.waitFor();
} finally {
p.destroy();
e.shutdown();
}
}
关于java - 通过 ProcessBuilder 运行时 Shell 脚本挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62056644/
是否可以将 ProcessBuilder 创建的一个进程的输出传递给另一个 ProcessBuilder 创建的另一个进程?例如,如果我尝试执行此 shell 命令: ls | grep build.
我在使用 ProcessBuilder 运行项目中的类时遇到问题。我的代码: public class Main { public static void main(String[] args
我有一段类似这样的代码 File f = new File("Audio/Testing/mbgitr.wav"); try { ProcessBuilder pb = new
我试图了解更多关于 ffmpeg 在 JavaCV for android studio 中的使用情况,并且对于我正在尝试使用 ProcessBuilder 的上述任务。我尝试编写一个简单的程序来调试
我正在编写一个 Java 程序,它应该是 GUI 前端,它利用三级 C 程序为各种标签生成一些值。 但我不想硬编码 C 程序的路径。我只希望 Java 程序执行 C 程序,前提是它位于我运行 Java
我真的不熟悉使用线程,所以我希望有人能帮助我找出最好的方法。 我的 java 应用程序中有一个 JButton...当您单击该按钮时,我有一个进程生成器,它创建一个执行一些外部 python 代码的进
在主机“A”上,我通过将值插入数据库中的表来启动事务。一旦插入,我就会调用 processBuilder 来刷新主机“B”,而主机“B”又应该将更新的值从同一数据库表加载到缓存。但这些值没有被加载。
我关注了这个tutorial为插件代码实现java沙箱。插件代码使用以下权限运行: private PermissionCollection pluginPermissions() { Per
这个问题已经有答案了: process.waitFor() never returns (12 个回答) 已关闭 3 年前。 我使用以下代码运行命令: open class AppRunner {
我正在尝试使用 Linux 下的 ProcessBuilder 类将 mp3 文件解码为 wav 文件。由于某种原因,该过程没有停止,因此我必须手动取消它。 有人可以给我一些提示吗?我认为引用的代码很
好吧,我尝试了十几种不同的方法,但没有成功。我想执行自定义 exe 并获取输出。它在命令提示符下运行良好。我让“dir”工作正常,但custom.exe 不行。这是代码: List command
在尝试执行代码块(更具体地说是 Java 中的 ProcessBuilder 类)时,我遇到了一个奇怪的问题 有效的代码: package modules.user.verify; import ja
我在使用 > 运算符写入 Process Builder 中的文件时遇到问题。实际的过程将运行良好,让我使用 InputStreamReader 等来解析输出。我希望使用命令行将进程写入文件,例如 >
使用 ProcessBuilder 运行命令时可以规定时间吗?像这样: ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "d
我想在 JAVA 程序中执行 EXE 文件。 它工作正常,但我希望 EXE 的输出立即出现在我的 JAVA 程序的文本区域中。 目前,我在“ping”命令完全完成后得到输出(因此 JAVA 程序挂起大
我正在使用 Java ProcessBuilder 执行两个 shell 脚本。我希望两次执行之间有 10 秒的时间间隔。这就是我使用线程的原因。但以下代码不会执行 shell 脚本(没有它们执行的线
我正在运行这个(kotlin-)代码: val proc = ProcessBuilder("sed", "s/bla/blub/g").start() val reader = BufferedRe
我正在使用进程生成器从 postgres 运行 psql 命令来调用 copy 命令来导出一些表。 我的工作流程如下: String sql = "\"\\copy ( SELECT * from t
我需要使用 java.lang.ProcessBuilder 将使用“sudo”和“su”的不同 sh 命令从我的 java 应用程序传递到 Linux。 这些命令非常相似,但有些有效,有些无效。当我
我今天在设置一组本地通信程序时遇到了这个问题。基本上,我的一个应用程序正在向另一个应用程序发送一些数据,并且该数据的一部分是一个包含要执行的命令的字符串(就像您从命令行执行的那样)。举例来说: g++
我是一名优秀的程序员,十分优秀!