双击运行与命令行运行有什么区别?

849 阅读4分钟

背景

最近写了一个ideal的窗口插件,可以点击窗口中的按钮来执行一些操作,这些操作涉及一些文件夹的创建、文件复制、压缩等,其中耗时的操作有git clone以及使用gradle对代码进行打包操作。因为涉及到的操作比较多,所以将这些操作统一放到一个shell脚本里执行,这样,只需要执行一下shell脚本即可完成一系统操作。

待插件开发调试完毕并打包生成一个插件jar包给他人使用时发现不能正常执行,shell脚本中所有的代码都执行了,但==只有gradle打包过程只执行了一部分==。为什么说只执行了一部分呢,是因为日志里出现了执行日志,但日志只有几行就消失了,然后执行后续的指令,查看相关文件夹下没有相关产物出现,说明它确实没有正常执行。

通过添加日志排查发现插件执行的目录为/,考虑可能是运行的目录没有权限,于是将执行位置切换成有权限的位置,问题依然存在。

问题难点

  1. 不太了解是否是ideal有相关的限制,也未搜索到相关的问题
  2. ==shell脚本是通过Process.exec方法执行==的,无法监测到shell脚本里的命令执行情况
  3. 由于gradle脚本是使用java程序执行的,怀疑可能是java环境不一样,可我只安装了java8,会有什么不同呢? 基于以上两点原因,问题解决陷入僵局...

转机

插件不能正常执行,但工具还是要用的,插件的界面是使用swing编写,所以可以直接打包成一个普通的Jar程序。在命令行里使用jar -jar 执行打包好的jar包一切正常。一次偶然的双击jar包,启动图形界面,执行相关操作时发现了与ideal插件一样的问题,即gradle打包命令只执行了一部分。看到此现象顿时感觉出现了转机,感觉问题很快就会被解决,至少现在可以证明此问题不是ideal插件相关的问题了。现在的问题转变成双击运行与在命令行运行有什么不同?

双击运行与命令行运行有什么不同?

google和百度都没有发现有什么不同,找到的只是如何让jar可以双击运行,并没有找到双击运行相比于在命令行中运行有什么不同。问了一圈周围的同事也没有发现有什么不同,但大家还都是怀疑java环境问题。

于是在shell脚本里添加java -version来查看,但却没有看到有信息输出,而直接在命令行里执行shell脚本是可以看到java版本信息输出的。将java -version执行的结果直接赋值到一个变量中,再打印变量,还是没有输出。同时执行shell脚本时添加了-v参数,正常情况下会打印出执行的相关指令的,但实现却没有输出任何执行过的指令。

后来想起Process类是有两个输入流的,一个正常的input,另一个是errorInput,而我只读取了正常的input流,于是添加上对errorInput的读取。呵,好家伙,添加后,这些没有正常输出的信息都从错误流里输出了,包括java版本信息、执行过的指令输出,其中最重要的信息是它输出了gradle执行过程的错误信息,==没有ANDROID_HOME变量==。而ANDROID_HOME是在环境变量里配置的,打印出环境变量,果然不一样:==双击运行相比于在命令行运行,环境变量少了很多,用户自己配置的环境变量都不在其中==。

解决问题

知道了双击运行与命令行运行的区别,解决起来就简单了,只需要在shell脚本里添加source命令将用户配置的环境变量加载进去即可。添加环境变量后,验证通过,与命令行运行效果相同。

source /etc/profile
source /Users/client/.zshrc
source /Users/client/.bashrc
source /Users/client/.profile
source /Users/client/.bash_profile

总结

  1. 要尽量获取更多的信息用于排查问题 排查问题遇到的障碍是什么呢?主要还是没有足够的信息来判断问题根源。如使用Process执行脚本时,还有一个错误信息流,没有获取这个流的信息

  2. 要敢于怀疑 在最初没有使用Process的错误信息流,主要是感觉shell运行中没有出现什么错误,即使出现错误了,也是shell脚本执行的程序来输出,所以就忽略了此信息流,导致没有足够的信息来判断错误的根源,无排查的思路。

  3. 环境变量问题