Featured image of post java不能执行linux命令

java不能执行linux命令

又来整活了

环境

  • 银河麒麟(Kylin-Server-V10-SP3-General-Release-2303-arm64)

  • JDK-17.0.13

问题起因

我们有程序需要调用linux的命令,但是这一次打包以后发现,命令执行不了(其他功能未见异常),提示:

1
2
执行失败: Cannot run program "su": error=13, 权限不够
java.io.IOException: Cannot run program "su": error=13, 权限不够

排查过程:

1、开始觉得应该去掉su,改成类似:

1
Runtime.getRuntime().exec("sh ....");

但是,去掉了前面的su或者sudo,返回结果就变成 /bin/sh 没有权限了,准确的说执行任何东西都没有权限。

2、开始觉得是不是selinux搞的鬼,selinux关了,问题依旧。

3、怀疑是否是挂载点设置了noexec属性,排查后发现不是。(开始问chatgpt)

4、chatgpt让我执行的命令以前打印一下PATH,说可能是PATH有问题,实际PATH没问题,能正常获取到。(到这里开始,已经开始使用简单的程序去测试,而不是每次都拉起很重的程序)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.File;

public class ExecTest {

    public static void main(String[] args) {
        // 打印当前用户
        System.out.println("=== 当前用户 ===");
        execSimple(new String[]{"/bin/sh", "-c", "whoami"});

        // 打印 PATH 环境变量
        System.out.println("\n=== 当前 PATH ===");
        System.out.println(System.getenv("PATH"));

        // 执行 uname
        System.out.println("\n=== uname -m ===");
        execSimple(new String[]{"/bin/sh", "-c", "uname -m"});

        // 查看 /bin/sh 权限
        System.out.println("\n=== /bin/sh 权限 ===");
        execSimple(new String[]{"/bin/sh", "-c", "ls -l /bin/sh"});

        // 查看挂载参数
        System.out.println("\n=== 挂载参数(可能含 noexec) ===");
        execSimple(new String[]{"/bin/sh", "-c", "mount | grep -E ' / |/bin|/opt|/usr'"});

        // 测试 sudo(不推荐)
        System.out.println("\n=== 尝试 sudo(可能失败) ===");
        execSimple(new String[]{"/bin/sh", "-c", "sudo uname -m"});
    }

    private static void execSimple(String[] command) {
        try {
            Process process = new ProcessBuilder(command)
                    .redirectErrorStream(true)
                    .start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            int exitCode = process.waitFor();
            System.out.println("退出码: " + exitCode);
        } catch (Exception e) {
            System.err.println("执行失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

5、chatgpt觉得是银河麒麟的问题,我自己也这么觉得,疯狂找麒麟的安全设置,调了我很久,最终问题依旧。(到这儿我放弃chatgpt了)

6、在心灰意冷之际,因为服务器上还有一个jdk,跟这个大版本相同,但是小版本不同(那个是17.0.12这个是17.0.13),用这个jdk执行了一下我的测试程序,通过了。。。(啥?)

7、然后把jdk换了,程序确实好了。(但是why?jdk突然新增了什么特性?)然后开始漫长的查找,最终决定同版本的从官网搞一个上去试试,但是也能跑(吐血

8、那就是持续集成打包出问题了,开始使用diff -r 对比官网jdk和打包jdk,一模一样!(再次吐血

9、不如跟一跟看看到底哪里的问题,一个strace上去:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
$ strace -f -e trace=process $JAVA_HOME/bin/java ExecTest
execve("$JAVA_HOME/bin/java", ["$JAVA_HOME/bin/ja"..., "ExecTest"], 0xffffdd70e370 /* 29 vars */) = 0
clone(child_stack=0xfffcd0f5cae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378386 attached
, parent_tid=[378386], tls=0xfffcd0f5d8e0, child_tidptr=0xfffcd0f5d2b0) = 378386
[pid 378386] clone(child_stack=0xfffcac38eae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378387 attached
, parent_tid=[378387], tls=0xfffcac38f8e0, child_tidptr=0xfffcac38f2b0) = 378387
[pid 378386] clone(child_stack=0xfffca7ffeae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378388 attached
, parent_tid=[378388], tls=0xfffca7fff8e0, child_tidptr=0xfffca7fff2b0) = 378388
[pid 378386] clone(child_stack=0xfffca7deeae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378389 attached
, parent_tid=[378389], tls=0xfffca7def8e0, child_tidptr=0xfffca7def2b0) = 378389
[pid 378386] clone(child_stack=0xfffca546eae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378390 attached
, parent_tid=[378390], tls=0xfffca546f8e0, child_tidptr=0xfffca546f2b0) = 378390
[pid 378386] clone(child_stack=0xfffca525eae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378391 attached
, parent_tid=[378391], tls=0xfffca525f8e0, child_tidptr=0xfffca525f2b0) = 378391
[pid 378386] clone(child_stack=0xfffca4f0eae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378392 attached
, parent_tid=[378392], tls=0xfffca4f0f8e0, child_tidptr=0xfffca4f0f2b0) = 378392
[pid 378386] clone(child_stack=0xfffca4cfeae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378393 attached
, parent_tid=[378393], tls=0xfffca4cff8e0, child_tidptr=0xfffca4cff2b0) = 378393
[pid 378386] clone(child_stack=0xfffca4afeae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378394 attached
, parent_tid=[378394], tls=0xfffca4aff8e0, child_tidptr=0xfffca4aff2b0) = 378394
[pid 378386] clone(child_stack=0xfffca45deae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378395 attached
, parent_tid=[378395], tls=0xfffca45df8e0, child_tidptr=0xfffca45df2b0) = 378395
[pid 378386] clone(child_stack=0xfffca43deae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378396 attached
, parent_tid=[378396], tls=0xfffca43df8e0, child_tidptr=0xfffca43df2b0) = 378396
[pid 378386] clone(child_stack=0xfffc7bffeae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378397 attached
, parent_tid=[378397], tls=0xfffc7bfff8e0, child_tidptr=0xfffc7bfff2b0) = 378397
[pid 378386] clone(child_stack=0xfffc7bdfeae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378398 attached
, parent_tid=[378398], tls=0xfffc7bdff8e0, child_tidptr=0xfffc7bdff2b0) = 378398
[pid 378386] clone(child_stack=0xfffc7bbfeae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378399 attached
, parent_tid=[378399], tls=0xfffc7bbff8e0, child_tidptr=0xfffc7bbff2b0) = 378399
[pid 378386] clone(child_stack=0xfffc7b9feae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378400 attached
, parent_tid=[378400], tls=0xfffc7b9ff8e0, child_tidptr=0xfffc7b9ff2b0) = 378400
[pid 378386] clone(child_stack=0xfffc7b7feae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378401 attached
, parent_tid=[378401], tls=0xfffc7b7ff8e0, child_tidptr=0xfffc7b7ff2b0) = 378401
[pid 378386] clone(child_stack=0xfffc7b5feae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378402 attached
, parent_tid=[378402], tls=0xfffc7b5ff8e0, child_tidptr=0xfffc7b5ff2b0) = 378402
[pid 378386] clone(child_stack=0xfffc7b3eeae0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTIDstrace: Process 378403 attached
, parent_tid=[378403], tls=0xfffc7b3ef8e0, child_tidptr=0xfffc7b3ef2b0) = 378403
=== 当前用户 ===
[pid 378386] clone(child_stack=0xfffca41e0000, flags=CLONE_VM|CLONE_VFORK|SIGCHLDstrace: Process 378404 attached
 <unfinished ...>
[pid 378404] execve("$JAVA_HOME/lib/jspawnhelper", ["12:15"], 0xffffe9432d60 /* 29 vars */) = -1 EACCES (权限不够)
[pid 378404] exit_group(127)            = ?
[pid 378404] +++ exited with 127 +++
[pid 378386] <... clone resumed>)       = 378404
[pid 378385] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=378404, si_uid=0, si_status=127, si_utime=0, si_stime=0} ---
[pid 378386] wait4(378404, NULL, 0, NULL) = 378404
执行失败: Cannot run program "/bin/sh": error=13, 权限不够
java.io.IOException: Cannot run program "/bin/sh": error=13, 权限不够
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
        at ExecTest.execSimple(ExecTest.java:37)
        at ExecTest.main(ExecTest.java:10)
Caused by: java.io.IOException: error=13, 权限不够
        at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
        at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:314)
        at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)
        ... 3 more

=== 当前 PATH ===
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin

=== uname -m ===
[pid 378386] clone(child_stack=0xfffca41b0000, flags=CLONE_VM|CLONE_VFORK|SIGCHLDstrace: Process 378405 attached
 <unfinished ...>
[pid 378405] execve("$JAVA_HOME/lib/jspawnhelper", ["12:15"], 0xffffe9432d60 /* 29 vars */) = -1 EACCES (权限不够)
[pid 378405] exit_group(127)            = ?
[pid 378405] +++ exited with 127 +++
[pid 378386] <... clone resumed>)       = 378405
[pid 378385] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=378405, si_uid=0, si_status=127, si_utime=0, si_stime=0} ---
[pid 378386] wait4(378405, NULL, 0, NULL) = 378405
执行失败: Cannot run program "/bin/sh": error=13, 权限不够
java.io.IOException: Cannot run program "/bin/sh": error=13, 权限不够
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
        at ExecTest.execSimple(ExecTest.java:37)
        at ExecTest.main(ExecTest.java:18)
Caused by: java.io.IOException: error=13, 权限不够
        at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
        at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:314)
        at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)
        ... 3 more

=== /bin/sh 权限 ===
[pid 378386] clone(child_stack=0xfffca41b0000, flags=CLONE_VM|CLONE_VFORK|SIGCHLDstrace: Process 378406 attached
 <unfinished ...>
[pid 378406] execve("$JAVA_HOME/lib/jspawnhelper", ["12:15"], 0xffffe9432d60 /* 29 vars */) = -1 EACCES (权限不够)
[pid 378406] exit_group(127)            = ?
[pid 378406] +++ exited with 127 +++
[pid 378386] <... clone resumed>)       = 378406
[pid 378385] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=378406, si_uid=0, si_status=127, si_utime=0, si_stime=0} ---
[pid 378386] wait4(378406, NULL, 0, NULL) = 378406
执行失败: Cannot run program "/bin/sh": error=13, 权限不够
java.io.IOException: Cannot run program "/bin/sh": error=13, 权限不够
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
        at ExecTest.execSimple(ExecTest.java:37)
        at ExecTest.main(ExecTest.java:22)
Caused by: java.io.IOException: error=13, 权限不够
        at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
        at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:314)
        at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)
        ... 3 more

=== 挂载参数(可能含 noexec) ===
[pid 378386] clone(child_stack=0xfffca41b0000, flags=CLONE_VM|CLONE_VFORK|SIGCHLDstrace: Process 378407 attached
 <unfinished ...>
[pid 378407] execve("$JAVA_HOME/lib/jspawnhelper", ["12:15"], 0xffffe9432d60 /* 29 vars */) = -1 EACCES (权限不够)
[pid 378407] exit_group(127)            = ?
[pid 378407] +++ exited with 127 +++
[pid 378386] <... clone resumed>)       = 378407
[pid 378385] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=378407, si_uid=0, si_status=127, si_utime=0, si_stime=0} ---
[pid 378386] wait4(378407, NULL, 0, NULL) = 378407
执行失败: Cannot run program "/bin/sh": error=13, 权限不够
java.io.IOException: Cannot run program "/bin/sh": error=13, 权限不够
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
        at ExecTest.execSimple(ExecTest.java:37)
        at ExecTest.main(ExecTest.java:26)
Caused by: java.io.IOException: error=13, 权限不够
        at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
        at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:314)
        at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)
        ... 3 more

=== 尝试 sudo(可能失败) ===
[pid 378386] clone(child_stack=0xfffca41b0000, flags=CLONE_VM|CLONE_VFORK|SIGCHLDstrace: Process 378408 attached
 <unfinished ...>
[pid 378408] execve("$JAVA_HOME/lib/jspawnhelper", ["12:15"], 0xffffe9432d60 /* 29 vars */) = -1 EACCES (权限不够)
[pid 378408] exit_group(127)            = ?
[pid 378408] +++ exited with 127 +++
[pid 378386] <... clone resumed>)       = 378408
[pid 378385] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=378408, si_uid=0, si_status=127, si_utime=0, si_stime=0} ---
[pid 378386] wait4(378408, NULL, 0, NULL) = 378408
执行失败: Cannot run program "/bin/sh": error=13, 权限不够
java.io.IOException: Cannot run program "/bin/sh": error=13, 权限不够
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
        at ExecTest.execSimple(ExecTest.java:37)
        at ExecTest.main(ExecTest.java:30)
Caused by: java.io.IOException: error=13, 权限不够
        at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
        at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:314)
        at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)

果然是自己蠢了,lib/jspawnhelper没有权限,为啥没有早点怀疑jdk呢,只是检查了bin目录就算了,lib目录权限没检查,觉得其他功能正常就完全忽略了jdk可能存在问题。(打包那边把lib目录部分可执行文件的执行权限搞丢了)

赋权、测试加反馈,问题完。