我正在尝试编写一个bash
命令行工具,该工具在安装后立即可用,即在调用其安装脚本的同一个shell中。让我们说install-script.sh
(专为Ubuntu设计)看起来像:
# Get the script's absolute path:
pushd `dirname $0` > /dev/null
SCRIPTPATH=`pwd`
popd > /dev/null
# Add lines to bash.bashrc to export the environment variable:
echo "SCRIPT_HOME=${SCRIPTPATH}" >> /etc/bash.bashrc
echo "export SCRIPT_HOME" >> /etc/bash.bashrc
# Create a new command:
cp ${SCRIPTPATH}/newcomm /usr/bin
chmod a+x /usr/bin/newcomm
我们的想法是新命令newcomm
使用SCRIPT_HOME
环境变量来引用主脚本 - 这也在SCRIPTPATH
中:
exec "${SCRIPT_HOME}/main-script.sh"
现在,更新后的bash.bashrc
尚未加载到父shell中。更糟糕的是,我不能在脚本中source
它 - 它在子shell中运行。使用export
更改父shell中的SCRIPT_HOME
充其量只会导致问题,但即使这样也是不可能的。另请注意,安装脚本需要使用sudo
运行,因此无法使用source
从父shell调用它。
应该可以,因为像apt
这样的包管理器可以做到这一点。是否有强大的方法来修补我的方法?这通常是怎么做的,是否有编写bash安装程序的良好指南?
答案 0 :(得分:3)
修改当前shell的唯一方法是获取脚本。这是不可避免的,所以从那里开始吧。写一个source
d的脚本。该脚本将依次调用您当前的脚本。
您当前的脚本需要与源代码进行通信才能告诉它要更改的内容。常见的方法是回显可由调用者直接执行的变量赋值。例如:
printf 'export SCRIPT_HOME=%q\n' "$SCRIPTPATH"
将printf
与%q
一起使用可确保正确转义任何特殊字符。
然后让source
d脚本eval
成为内部脚本。
eval "$(sudo install-script.sh)"
如果要隐藏顶级脚本的source
,可以将其隐藏在别名或shell函数后面。
答案 1 :(得分:3)
你做不到。也不能apt
。
包管理器只需将所需的数据/变量写入文件,这些文件可由程序本身,程序补丁或包装程序读取。
在/etc/default/*
中可以找到很好的例子。这些是具有可变定义的文件,有些甚至有助于描述它们的来源:
$ cat /etc/default/ssh
# Default settings for openssh-server. This file is sourced by /bin/sh from
# /etc/init.d/ssh.
# Options to pass to sshd
SSHD_OPTS=
您会注意到在安装软件包后,当前shell中没有设置任何选项,因为程序会以某种方式直接从文件中获取它们。