【问题标题】:Bash: Script Calling Gnome Terminal Leads To Child Process Error?Bash:脚本调用 Gnome 终端导致子进程错误?
【发布时间】:2022-01-16 16:43:14
【问题描述】:

我正在尝试让脚本打开一个新的终端窗口,然后在该终端中调用另一个脚本。

我收到了错误:

为此终端创建子进程时出错

我认为这与尝试运行子进程的调用脚本有关。

我已经在 gnome-terminal 中尝试了 --x 选项。它不工作。 我确信有一种方法可以告诉终端在新终端中执行命令。我似乎无法在任何地方的文档中找到它。

有人遇到过这个问题并解决了吗?

参考问题代码:57、58行:

sudo gnome-terminal -x --window --wait --tab --active --title="$1" --geometry=120X60 \
--working-directory="$code_directory"  --command "$file_path"

完整上下文中的脚本:

#!/bin/bash
# Runs last modified script in new Terminal window tab in dev qube.

# Global vars
qube_name='dev'
code_directory='/home/user/Documents/'
last_modified='' # Last modified file in code directory.
file_path='' # Full file path of last modified file.


# Gets the last modified file in the code directory.
get_filename(){
    cd "$code_directory"
     last_modified=$(ls -t | head -n1)
    echo "$last_modified"
}


# Returns full file path.
get_full_path(){
    # $1=filename
    export file_path="$code_directory$1"
    echo "$file_path"
}


# Stops script if last modified file is this one.
check_filename(){
    # $1=file path
    # Guard clause to prevent recursive call.
    if [ "$1" == 'run_last_modified.sh' ]; then
        msg='Last modified file is run_last_modified.sh.
            Stopping execution...'
        notify-send "$msg";echo "$msg"
        exit
    fi
    echo "$1"
}

# Makes file executable if it isn't already.
make_executable(){
    #$1=file_path
    msg="Making $file_path executable..."
    echo "$msg"
    sudo chmod +x "$1"
    echo "$1"
}

# Opens a new terminal window and runs the file.
run_in_terminal(){
    #$1=file_path
    msg="Running $1 in $qube_name Terminal..."
    notify-send "$msg";echo "$msg"

    # -x option deprecated.  

    sudo gnome-terminal -x --window --wait --tab --active --title="$1" --geometry=120X60 \
    --working-directory="$code_directory"  --command "$file_path"

    # For dom0
    # qvm-run "$qube_name gnome-terminal -e $file_path"
}

run(){
    # Pipeline
    last_modified=$(get_filename)
    file_path=$(get_full_path)
    check_filename "$file_path"
    make_executable "$file_path" 
    run_in_terminal "$file_path"
}

run

################## TESTS #################
# Note to self: Comment out run ^^^ before running tests.

tests(){
    # get filename test.
    last_modified=$(get_filename)
    msg="Last modified: $last_modified"
    notify-send "$msg";echo "$msg"

    # get filepath test.
    file_path=$(get_full_path "$last_modified")
    msg="File path: $file_path"
    notify-send "$msg";echo "$msg"

    # Check filename test.
    # last_modified='run_last_modified.sh'
    # check_filename # Should stop execution.

    # Make executable tests.
    make_executable "$file_path"

}

# tests

【问题讨论】:

  • 我建议使用跟踪日志运行脚本,如bash -x your_script(或将set -x 放在脚本顶部附近的某个位置);这样你就可以看到它正在运行的确切的gnome-terminal 命令,并尝试使用该命令来找到一个符合你预期的变体。
  • 顺便说一句,虽然这似乎不是您现在遇到的问题(这将是一条不同的错误消息),但使用 sudo 运行的命令无法运行并不罕见由于 Xauthority 等环境变量未传播而连接到 X 服务器。如果您希望您的程序继续使用具有更严格安全性的较新发行版,我建议在终端启动之后而不是之前进行权限提升;这也减少了对终端本身的攻击机会,允许直接访问 root。
  • 需要一个单独的终端是一个常见的初学者请求,但最终往往是一个坏主意。也许您可以运行一个后台进程并将输出输出到一个文件,您可以在需要时从任何可用的终端检查该文件。
  • (请参阅nvd.nist.gov/vuln/detail/CVE-2021-27135 作为上述针对终端本身的攻击示例)
  • 要求交互式 I/O 是要避免的单独的模式。您至少希望在命令行中提供一个选项来指定参数等。

标签: bash terminal xterm gnome-terminal


【解决方案1】:

-x--command 是不正确/过时的选项,试试这个:

sudo gnome-terminal --window --wait --tab --active --geometry=120X60 \
    --title="$1" --working-directory="$code_directory" -- "$file_path"

保持终端窗口打开:

sudo gnome-terminal --window --wait --tab --active --geometry=120X60 \
    --title="$1" --working-directory="$code_directory"\
    -- bash -c "$file_path; exec bash"

【讨论】:

  • 谢谢。那行得通。除了在被调用脚本完成后关闭终端窗口。你知道可以保持终端窗口打开的标志吗?
  • 不错。现在完美运行。
  • 使用sudo 运行终端似乎是一个非常糟糕的主意。如果您需要在终端内部运行特权shell,请改为这样做。
  • @tripleee 你能向 OP 解释一下使用 sudo 有什么问题吗?
  • 基本安全卫生;用户 GUI 代码不应以特权运行。此外,这可能会使事情复杂化,因为 root 不应访问您的 $DISPLAY
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-12
  • 2014-12-08
  • 2011-12-10
  • 1970-01-01
  • 2017-11-24
  • 2013-09-26
  • 2017-04-29
相关资源
最近更新 更多