在processCmd方法中,主要流程有:
- 去除命令中的注释;
- 如果命令是
quit
或exit
,则退出; - 如果命令是
source
开头,则校验source
命令后面的文件是否存在,存在则执行processFile
; - 如果命令是以感叹号!开头,表明是
shell
命令,这时候直接调用shell
命令执行器执行; - 如果以上都不是,则说明是本地模式。然后获得命令处理器,并调用
processLocalCmd
执行命令。
这里说出了processCmd
向后的两个方向,第一个方向是processFile
,用于执行文件,第二个方向是processLocalCmd
,用于执行命令。
public int processCmd(String cmd) {
// CliSessionState 对象不再赘述
CliSessionState ss = (CliSessionState)SessionState.get();
ss.setLastCommand(cmd);
ss.updateThreadName();
// 刷新打印流,防止上个命令输出
ss.err.flush();
String cmd_trimmed = cmd.trim();
// tokenizeCmd将用户输入的指令从空格,制表符等出断开,得到token数组
String[] tokens = this.tokenizeCmd(cmd_trimmed);
int ret = 0;
// 如果命令是`quit`或`exit`,则退出
if (!cmd_trimmed.toLowerCase().equals("quit") && !cmd_trimmed.toLowerCase().equals("exit")) {
String shell_cmd;
// 如果命令是`source`开头,则校验`source`命令后面的文件是否存在,存在则执行`processFile`
if (tokens[0].equalsIgnoreCase("source")) {
shell_cmd = this.getFirstCmd(cmd_trimmed, tokens[0].length());
shell_cmd = (new VariableSubstitution(new HiveVariableSource() {
public Map<String, String> getHiveVariable() {
return SessionState.get().getHiveVariables();
}
})).substitute(ss.getConf(), shell_cmd);
File sourceFile = new File(shell_cmd);
// 如果source后跟的参数不是文件,就报错
if (!sourceFile.isFile()) {
this.console.printError("File: " + shell_cmd + " is not a file.");
ret = 1;
} else {
try {
// 不管再多操作,只要他是文件,最后也是交给processFile去执行
ret = this.processFile(shell_cmd);
} catch (IOException var11) {
// 处理失败了会输出报错的原因
this.console.printError("Failed processing file " + shell_cmd + " " + var11.getLocalizedMessage(), StringUtils.stringifyException(var11));
ret = 1;
}
}
// 如果命令是以感叹号!开头,表明是`shell`命令,这时候直接调用`shell`命令执行器执行
} else if (cmd_trimmed.startsWith("!")) {
shell_cmd = cmd_trimmed.substring(1);
shell_cmd = (new VariableSubstitution(new HiveVariableSource() {
public Map<String, String> getHiveVariable() {
return SessionState.get().getHiveVariables();
}
})).substitute(ss.getConf(), shell_cmd);
try {
ShellCmdExecutor executor = new ShellCmdExecutor(shell_cmd, ss.out, ss.err);
ret = executor.execute();
if (ret != 0) {
this.console.printError("Command failed with exit code = " + ret);
}
} catch (Exception var10) {
this.console.printError("Exception raised from Shell command " + var10.getLocalizedMessage(), StringUtils.stringifyException(var10));
ret = 1;
}
} else {
try {
CommandProcessor proc = CommandProcessorFactory.get(tokens, (HiveConf)this.conf);
// 去除上面各种类型,其他sql的主要执行方法为processLocalCmd
ret = this.processLocalCmd(cmd, proc, ss);
} catch (SQLException var9) {
this.console.printError("Failed processing command " + tokens[0] + " " + var9.getLocalizedMessage(), StringUtils.stringifyException(var9));
ret = 1;
}
}
} else {
ss.close();
System.exit(0);
}
ss.resetThreadName();
// 如果最后返回的ret为1,那么就表示执行失败。
return ret;
}