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]);
}