java调用shell脚本,不能操作/tmp目录下文件

2023-10-28

一、系统/平台

系统:openEuler-22.03

硬件平台:aarch64

二、问题

有个系统升级的需求,java端负责OTA升级包的下载,和版本维护,C端完成系统升级的后续操作,这时候就需要java端在下载完OTA升级包并校验通过之后,通知C端去完成系统升级。其中有三种方式可以完成这种进程间通讯:
1. 本地sock(UNIX Domain Socket)(最终选择的方式)

2. 读文件的方式:inotify 机制来读取

3. UDP网络通讯

备注:问题就是,
1. 通过本地socket的方式在/tmp目录下创建的domain socket文件,或通过读文件的方式在/tmp目录下创建一个.txt文件,在系统命令下调用都正常,但是通过systemd的service来调用就失败,最后的解决方案是,domain文件或.txt文件放到了/run目录下。(具体原因未找到)。

三、最终代码

ota.c (部分代码)

#include <stdio.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <stdbool.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <stdlib.h>

#include <pthread.h>

#define UNIX_DOMAIN_FILE    "/run/OTA_SOCKET.domain"


int listen_socket_create() {
	int fd = 0;
	int b_reuse = 1;
	struct sockaddr_un sun;

	if((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
		printf("socket\n");
		exit(-1);
	}
 
	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(int)); 

	bzero(&sun, sizeof(struct sockaddr_un));
	sun.sun_family = AF_LOCAL;
	
	if(!access(UNIX_DOMAIN_FILE, F_OK)) {
		unlink(UNIX_DOMAIN_FILE);//删除该文件	
	}

	strncpy(sun.sun_path, UNIX_DOMAIN_FILE, strlen(UNIX_DOMAIN_FILE));

	if(bind(fd, (struct sockaddr *)&sun, sizeof(sun))) {
		printf("bind\n");
	}

	if(listen(fd, 2) < 0) {
		printf("listen\n");
	}

	return fd;
}

void *ota_listen_pro(void *argv) {
	int newfd = -1;
	int read_len = 0;
	struct sockaddr_un cun;
	char buffer[15] = {0};
	const char *ota_msg = "ota_notice";
	socklen_t cun_addr_len = sizeof(cun);
	int listen_fd = listen_socket_create();

	while(1) {
		if((newfd = accept(listen_fd, (struct sockaddr *)&cun, &cun_addr_len)) < 0) {
			printf("accept error\n");
		}

		read_len = read(newfd, buffer, sizeof(buffer));
		if(!strncmp(ota_msg, buffer, strlen(ota_msg))) {
			printf("Enter OTA update\n");
			//enter_ota();
	}

	}

	return NULL;
}

void init_ota_listen() {
	pthread_t ota_listen_tid;

	pthread_create(&ota_listen_tid, NULL, ota_listen_pro, NULL);
	pthread_detach(ota_listen_tid);
	return;
}

int main()
{
     init_ota_listen();
}

ota_notice.c

#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <unistd.h>
#include "./rst_key.h"
#include <sys/un.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <strings.h>

#define UNIX_DOMAIN_FILE    "/run/OTA_SOCKET.domain"


int main(int argc, const char *argv[])
{
    int timeout = 5;
	int fd;
    struct sockaddr_un sun;
    const char buffer[] = "ota_notice";

	if((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
		perror("socket");
		exit(-1);
	}

	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_LOCAL;

    while((access(UNIX_DOMAIN_FILE, F_OK|W_OK) < 0)) {
		sleep(1);
		if(!timeout--) {
			exit(-1);
		}
    }

	strncpy(sun.sun_path, UNIX_DOMAIN_FILE, strlen(UNIX_DOMAIN_FILE));

	if(connect(fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
		perror("connect");
    }

    write(fd, buffer, sizeof(buffer));

    return 0;
}

/etc/systemd/system/ota_notice.service

[Unit]
Description=OTA notice Service
After=rc-local.service

[Service]
Type=simple
#ExecStart=/root/test.sh
WorkingDirectory=/root
ExecStart=/usr/soft/jdk1.8.0_201/bin/java JavaExecuteShell
PrivateTmp=true

[Install]
WantedBy=multi-user.target

/root/test.sh

#!/bin/bash

echo "execute......" > /root/test.log
/root/ota_notice

echo "done" >> /root/test.log

JavaExecuteShell.java

/**
 * java程序调用shell脚本
 */
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;
import java.io.IOException;


public class JavaExecuteShell {
    public static void main(String[] args) {
        try {
            //String cmd = "sh /root/test.sh "+args[0] +" "+args[1];
            String cmd = "sh /root/test.sh ";
            System.out.println("cmd = "+cmd);
            Process exec = Runtime.getRuntime().exec(cmd);
            String line;
            //要执行的程序可能输出较多,而运行窗口的缓冲区有限,会造成waitFor阻塞,利用这种方式可以在waitFor命令之前读掉输出缓冲区的内容
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
            while ((line = bufferedReader.readLine())!=null){
                System.out.println("result======="+line);
            }
            bufferedReader.close();
            //等待脚本执行完成
            exec.waitFor();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

四、部署/运行

  

部署:
cp ota ota_notice JavaExecuteShell.class test.sh /root 
cp ota_notice.service /etc/systemd/system/ota_notice.service

运行:
/root/ota &
sleep1
systemctl start ota_notice
sleep 1
systemctl status ota_notice

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java调用shell脚本,不能操作/tmp目录下文件 的相关文章

  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • 按字典顺序对整数数组进行排序 C++

    我想按字典顺序对一个大整数数组 例如 100 万个元素 进行排序 Example input 100 21 22 99 1 927 sorted 1 100 21 22 927 99 我用最简单的方法做到了 将所有数字转换为字符串 非常昂贵
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 如何在keycloak中动态编辑standalone.xml文件

    我正在尝试通过 docker 编辑standalone xml 并尝试添加 但 keycloak 正在使用它standalone xml 但我可以看到standalone xml 文件中的更改 我需要在standalone xml 文件中添
  • 在 Selenium WebDriver 上如何从 Span 标签获取文本

    在 Selenium Webdriver 上 如何从 span 标记检索文本并打印 我需要提取文本UPS Overnight Free HTML代码如下 div id customSelect 3 class select wrapper
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • 从java中的字符串数组中删除空值

    java中如何从字符串数组中删除空值 String firstArray test1 test2 test4 我需要像这样没有 null 空 值的 firstArray String firstArray test1 test2 test4
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 如何将实例变量传递到 Quartz 作业中?

    我想知道如何在 Quartz 中外部传递实例变量 下面是我想写的伪代码 如何将 externalInstance 传递到此作业中 public class SimpleJob implements Job Override public v
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • Spring Boot MSSQL Kerberos 身份验证

    目前在我的春季靴子中application properties文件中 我指定以下行来连接到 MSSql 服务器 spring datasource url jdbc sqlserver localhost databaseName spr
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐