Skip to content

Commit dff54fd

Browse files
committed
[os] detect shell charset
1 parent 5d50855 commit dff54fd

File tree

2 files changed

+80
-4
lines changed

2 files changed

+80
-4
lines changed

base/src/main/java/io/vproxy/base/util/OS.java

+73
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package io.vproxy.base.util;
22

3+
import java.nio.charset.Charset;
4+
import java.nio.charset.StandardCharsets;
5+
import java.util.ArrayList;
6+
import java.util.concurrent.TimeUnit;
7+
38
public class OS {
49
private static final String osname;
510
private static final String osversion;
@@ -79,4 +84,72 @@ public static boolean isLinux() {
7984
public static String arch() {
8085
return arch;
8186
}
87+
88+
private static Charset SHELL_CHARSET = null;
89+
90+
public static Charset shellCharset() {
91+
if (SHELL_CHARSET != null) {
92+
return SHELL_CHARSET;
93+
}
94+
var charsets = new ArrayList<Charset>();
95+
charsets.add(StandardCharsets.UTF_8);
96+
try {
97+
charsets.add(Charset.forName("GBK"));
98+
} catch (Throwable ignore) {
99+
}
100+
//noinspection UnnecessaryUnicodeEscape
101+
var testStr = "\u4F60\u597D\uFF0C\u4E16\u754C"; // 你好,世界
102+
String cmd;
103+
if (isWindows()) {
104+
cmd = "echo " + testStr;
105+
} else {
106+
cmd = "echo \"" + testStr + "\"";
107+
}
108+
for (var c : charsets) {
109+
var s = new String(cmd.getBytes(c), c);
110+
ProcessBuilder pb;
111+
if (isWindows()) {
112+
pb = new ProcessBuilder("cmd.exe", "/c", s);
113+
} else {
114+
pb = new ProcessBuilder("/bin/sh", "-c", s);
115+
}
116+
int exitCode;
117+
String stdout;
118+
String stderr;
119+
try {
120+
var p = pb.start();
121+
var ok = p.waitFor(500, TimeUnit.MILLISECONDS);
122+
if (!ok) {
123+
Logger.warn(LogType.SYS_ERROR, "failed executing cmd: " + cmd + ", command didn't finish in 500ms");
124+
try {
125+
p.destroyForcibly();
126+
} catch (Throwable ignore) {
127+
}
128+
continue;
129+
}
130+
exitCode = p.exitValue();
131+
stdout = new String(p.getInputStream().readAllBytes(), c);
132+
stderr = new String(p.getErrorStream().readAllBytes(), c);
133+
} catch (Exception e) {
134+
Logger.warn(LogType.SYS_ERROR, "failed executing cmd: " + cmd, e);
135+
continue;
136+
}
137+
if (exitCode != 0) {
138+
Logger.warn(LogType.SYS_ERROR, "failed executing cmd: " + cmd + ", exitCode = " + exitCode +
139+
", stdout = " + stdout + ", stderr = " + stderr);
140+
continue;
141+
}
142+
stdout = stdout.trim();
143+
if (testStr.equals(stdout)) {
144+
Logger.alert("shell charset is determined: " + c + ", getting result: " + stdout);
145+
SHELL_CHARSET = c;
146+
return c;
147+
} else {
148+
Logger.warn(LogType.ALERT, "shell charset is not " + c + ", getting result: `" + stdout + "`");
149+
}
150+
}
151+
Logger.warn(LogType.ALERT, "shell charset cannot be determined, using UTF-8 by default");
152+
SHELL_CHARSET = StandardCharsets.UTF_8;
153+
return SHELL_CHARSET;
154+
}
82155
}

base/src/main/java/io/vproxy/base/util/Utils.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -599,15 +599,18 @@ public static ExecuteResult execute(String script, int timeout, boolean getResul
599599
}
600600
File file = File.createTempFile("script", OS.isWindows() ? ".bat" : ".sh");
601601
try {
602-
Files.writeString(file.toPath(), script);
602+
script = "@echo off\r\n" + script;
603+
Files.writeString(file.toPath(), script, OS.shellCharset());
603604
if (!file.setExecutable(true)) {
604-
throw new Exception("setting executable to script " + file.getAbsolutePath() + " failed");
605+
throw new Exception("chmod +x " + file.getAbsolutePath() + " failed");
605606
}
607+
var filePath = file.getAbsolutePath();
608+
filePath = new String(filePath.getBytes(OS.shellCharset()), OS.shellCharset());
606609
ProcessBuilder pb;
607610
if (OS.isWindows()) {
608-
pb = new ProcessBuilder("cmd.exe", "/c", file.getAbsolutePath());
611+
pb = new ProcessBuilder("cmd.exe", "/c", filePath);
609612
} else {
610-
pb = new ProcessBuilder(file.getAbsolutePath());
613+
pb = new ProcessBuilder(filePath);
611614
}
612615
return execute(pb, timeout, getResult);
613616
} finally {

0 commit comments

Comments
 (0)