java调用linux命令带星号的问题,ProcessBuilder无法执行带星号的shell命令

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

有个需求,需要在本地生成数据文档,然后scp到另外一个服务器上。我是用ProcessBuilder来执行scp命令的,调试的时候发现这个scp命令会失败,报No such file or directory。

代码如下: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

88import java.io.*;

import java.util.ArrayList;

import java.util.List;

public class{

public static void main(String[] args){

Shell s = new Shell();

String cmd = "scp -r /data/*.json [email protected]:/home/test/data/";

s.exec();

}

*

* @return

*/

public void exec(String cmd){

try {

// final Process process = Runtime.getRuntime().exec(cmd);

String[] commandSplit = cmd.split(" ");

List lcommand = new ArrayList();

for (int i = 0; i < commandSplit.length; i++) {

lcommand.add(commandSplit[i]);

}

System.out.println(lcommand);

ProcessBuilder processBuilder = new ProcessBuilder(lcommand);

//将标准输出和标准错误流合并

processBuilder.redirectErrorStream(true);

final Process process = processBuilder.start();

System.out.println("start run cmd=" + cmd);

//处理InputStream的线程

new Thread() {

public void run(){

BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));

String line = null;

try {

while ((line = in.readLine()) != null) {

System.out.println("output: " + line);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

in.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}.start();

new Thread() {

@Override

public void run(){

BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream()));

String line = null;

try {

while ((line = err.readLine()) != null) {

System.out.println("err: " + line);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

err.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}.start();

process.waitFor();

System.out.println("finish run cmd=" + cmd);

} catch (Exception e) {

e.printStackTrace();

}

}

}

执行的shell命令如下:1scp -r /data/*.json [email protected]:/home/test/data/

因为这段代码,之前执行其他命令是没有问题的,因此猜测和这次执行的这个命令有关系。然后经过调试,发现有2个问题:

如果命令中带有星号,就会导致执行不成功

这个还没找到比较好的解决方案,目前想到两种降级方案:

将shell命令放入一个单独的文档

比如我将上述命令写入shell.sh文档,然后再通过Java去执行这个脚本文档。

这样的好处是如果后续命令有变更,只需要修改shell.sh即可,不用重新编译发布Java进程;

弊端就是如果shell命令里面包含一些和环境相关的变量,处理起来会麻烦一点。比如针对上面这个命令,如果开发环境、测试环境和正式环境的同步服务器ip不一样,那么就需要Java代码先读取到环境变量,然后根据环境变量读取对应的ip配置信息,然后传入这个shell.sh脚本。

将星号改为具体的值

比如上面这个/data/*.json,实际上在/data目录下,有3个文档(1A0001.json、399001.json、399006.json),那么我可以执行三次命令,将文档同步过去:1

2

3scp -r /data/1A0001.json [email protected]:/home/test/data/

scp -r /data/399001.json [email protected]:/home/test/data/

scp -r /data/399006.json [email protected]:/home/test/data/

这个方案仅在文档数量非常少的情况下才可以用;一旦文档数很多,这个方案就不可行了。

如果命令中带有多余的空格,也会导致执行不成功

我写的命令里面,json和upload之间有2个空格,ProcessBuilder的构造函数接收的参数是一个List,我将上面的字符串命令分割成List的时候,就会出现一个空字符串元素,进而导致最终执行命令失败。如果用Runtime.getRuntime().exec(cmd)则没有问题,因为这个方法接收的参数可以是一个完整的命令的字符串。

这个比较好解决,对分割后的List的每个元素做个处理即可:1

2

3

4

5

6

7

8

9String[] commandSplit = cmd.split(" ");

List lcommand = new ArrayList();

for (int i = 0; i < commandSplit.length; i++) {

// 避免命令中有多余的空格

if (commandSplit[i].equals("")) {

continue;

}

lcommand.add(commandSplit[i]);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值