我有一个GUI macOS应用程序,也可以从终端启动,带有可选的命令行参数.
当使用参数启动时,我喜欢以"cmdline"模式运行应用程序,其中我不显示任何UI,而是仅通过stdin + stdout进行通信.
我可以像这样检测这个cmdline模式:
BOOL cmdMode = NSProcessInfo.processInfo.arguments.count > 1;
Run Code Online (Sandbox Code Playgroud)
(arg 0始终是可执行文件的路径,因此任何更多的args都将手动传递args).
现在,这是一个大问题:
如果用户在没有来自终端的参数的情况下调用我的应用程序(通过在Contents/MacOS中调用应用程序的可执行文件,即不通过opencmd),我也想进入cmdline模式.我怎么检测到这个?
注意:较旧的OS X版本确实传递了一个"-psn ..."参数,该参数在不存在时可用于检测cmdline的启动,但是当从这个版本启动应用程序时,最近的macOS版本似乎不再传递此参数Finder,所以我不能再用它来检测了.
更新
我意识到我几乎可以通过检查某些环境变量的存在来正确解决这个问题:
TERM并且PWD仅在从终端启动应用程序时设置,而不是从Finder启动.
但是,我也希望能够分辨直接启动(在Contents/MacOS dir中执行)与使用open命令启动之间的区别,因为我认为open cmd相当于通过Finder或其他应用程序通过Launch打开应用程序服务.
简而言之,问题可能还有:检测启动服务是否启动了应用程序
为了记录,这里是来自的值environ().标有星号的那些仅在从Terminal.app调用时才存在,但在从Finder中调用时不存在:
__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0
* _=/Applications/Myapp.app/Contents/MacOS/Myapp
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.laVQnD7IXl/Render
HOME=/Users/username
* LANG=en_US.UTF-8
* LC_ALL=en_US.UTF-8
* LC_CTYPE=UTF-8
LOGNAME=username
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
* PWD=/Users/username
SHELL=/bin/bash
* SHLVL=1
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.KeHv8KNuuk/Listeners
* TERM_PROGRAM_VERSION=388.1.2
* TERM_PROGRAM=Apple_Terminal
* TERM_SESSION_ID=EF2C59E6-D661-45BE-B7EF-7A0E71158C8D
* TERM=xterm-color
TMPDIR=/var/folders/hm/ycnxcbwx8xl1v7008k8wnpjh0000gn/T/
USER=username
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
Run Code Online (Sandbox Code Playgroud)
但是,使用Launch Services启动的应用程序(例如在Finder中双击时)没有任何独特的值.
我有一个Deno应用程序,我希望将一些命令行参数传递给它。我搜索了手册,但一无所获。
我尝试使用 Node.js 中使用的相同命令,假设它们可能会为 std 库共享一些命令,但效果不佳。
var args = process.argv.slice(2);
// Uncaught ReferenceError: process is not defined
Run Code Online (Sandbox Code Playgroud)
有什么建议?
我想在VSCode中调试C ++项目(在Mac上,使用GDB或LLDB)。程序本身接受命令行参数,例如
./prog -input cf file_x.txt
Run Code Online (Sandbox Code Playgroud)
在命令行上在GDB中启动调试会话时,这种方法可以正常工作。
在VSCode中,我试图适应launch.json这种阅读方式(仅显示相关行):
"program": "${workspaceRoot}/build/prog",
"args": [
"-input cf",
"path_to/file_x.txt"
]
Run Code Online (Sandbox Code Playgroud)
这样,我进入@"Unknown option: \"-input cf\"\r\n"了输出并且未调试过程;或者,我只尝试了一个这样的参数:
"program": "${workspaceRoot}/build/prog",
"args": [
"-input cf path_to/file_x.txt"
]
Run Code Online (Sandbox Code Playgroud)
结果相同。我错过了重要的事情吗?
我一直致力于一个使用PID /proc和命令行分析来验证系统进程的项目.我的代码必须由安全人员检查,他们设法用一条线来打破它......令人尴尬!
#!/usr/bin/env perl
$0="I am running wild"; # I had no clue you can do this!
system("cat /proc/$$/cmdline");
print("\n");
system("ps -ef | grep $$");
# do bad stuff here...
Run Code Online (Sandbox Code Playgroud)
我的问题:
我看到了上面的一些用例,比如隐藏在命令行上给出的密码(也是不好的做法)但是当我可以隐藏进程和欺骗时,我会看到更多的问题/问题cmdline.它有被允许的原因吗?这不是一个系统漏洞吗?
我该如何预防或发现这个?我已经研究了/procmount选项.我也知道可以使用lsof基于意外行为识别欺骗过程,但这在我的情况下不起作用.目前我正在使用一个简单的方法来检测是否cmdline包含至少一个null(\0)字符,该字符假定至少存在一个参数.在上面的代码中,空格需要用空值替换以绕过该检查,这是我无法在perl中找到的方法 - 写入第一个\0.
谢谢