英文:
Is there a way to stop 'child exited with status 1' error when running st -e 'curl wttr.in/LOCATION | less -R'?
问题
我正在尝试让脚本打开一个新的st
终端窗口并执行curl -s wttr.in/LOCATION | less -R
。
st -e "curl wttr.in/LOCATION | less -R"
会打开终端窗口,但会迅速关闭并在父窗口中返回child exited with status 1
。
我不想在/local/bin中创建一个命令来执行此请求。是否有更好的方法?
英文:
I'm trying to get a script to open a new st
terminal window and execute curl -s wttr.in/LOCATION | less -R
.
st -e "curl wttr.in/LOCATION | less -R"
opens the terminal window briefly, but closes and returns child exited with status 1
in the parent window.
I don't want to have to make a command in /local/bin just to make that request.
Is there a better way?
答案1
得分: 1
背景
设计良好的终端程序接受参数向量,可以直接使用 execve()
(或者更新的 posix_spawn()
系列系统调用)来调用,而不是用 system()
来调用shell命令。这样可以更安全地使用它们,避免需要对要作为参数传递到单个shell命令中的内容进行引用和转义(否则可能会容易受到注入攻击)。一些旧版本的终端程序接受 system()
-ready 的 sh
字符串(至少是为了兼容性),但你正在使用来自 https://suckless.org/ 的软件 - 他们已经决定做得更好。
简短/简单/不安全的修复
你正在使用的终端程序在 -e
后面接受一个命令和参数列表,作为单独的参数。因此,你需要像这样做:
st -e sh -c 'curl wttr.in/LOCATION | less -R'
在这里,sh
是要在终端中运行的命令,-c
是它的第一个参数,curl wttr.in/LOCATION | less -R
是它的第二个参数。
安全地执行这个操作
然而,如果你的位置来自一个变量,那么你应该将它与作为脚本传递的内容分开:
location="wttr.in/LOCATION"
st -e sh -c 'curl "$1" | less -R' sh "$location"
在这里,你的脚本 curl "$1" | less -R
使用 $0
作为 sh
来运行(在错误消息中用于描述失败的程序名称;你可以随意更改它),使用 $1
作为 wttr.in/LOCATION
。将URL传递给 $1
意味着包含像 $(rm -rf ~)
这样的字符串的URL不会删除你的主目录,就像使用不够谨慎的方法一样。
英文:
Background
Well-designed terminal programs take argument vectors that can be invoked directly with execve()
(or the newer posix_spawn()
family of syscalls), not shell commands for invocation with system()
. This makes them easier to use securely, avoiding the need to quote and escape contents to be passed as arguments into a single shell command (where without that escaping one is vulnerable to injection attacks). Some legacy terminals take system()
-ready sh
strings (at least for compatibility), but you're using software from https://suckless.org/ -- they've taken it on themselves to do better.
The Short/Simple/Insecure(?) Fix
The terminal you're using takes a command and argument list after -e
as separate arguments. Therefore, you want something like:
st -e sh -c 'curl wttr.in/LOCATION | less -R'
Here, sh
is the command to run in the terminal, -c
is its first argument, and curl wttr.in/LOCATION | less -R
is its second argument.
Doing This Securely
If your location is coming from a variable, however, then you should keep it out-of-band from the content passed as a script:
location="wttr.in/LOCATION"
st -e sh -c 'curl "$1" | less -R' sh "$location"
Here, your script curl "$1" | less -R
is run with a $0
of sh
(used in error messages to describe the name of the program that failed; change it however you like) and a $1
of wttr.in/LOCATION
. Passing the URL in $1
means that a URL containing a string like $(rm -rf ~)
won't delete your home directory, as it might with less incautious approaches.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论