如何从脚本更改 shell

如何从脚本更改 shell

我想将 shell 从 ksh 更改为 bash 并获取该.kshrc文件。我想依次执行以下几行命令:

bash
. ~/.kshrc
clear 

有谁能够帮助我?

答案1

让我们尝试首先以交互方式完成此任务,然后在脚本中完成。如果您的 kshrc 文件的第一行不是#~/usr/bin/env ksh#!/usr/bin/ksh类似的内容,您在问题中输入的内容将以交互方式工作。因此,我假设我们想要跳过 kshrc 文件的第一行并(尝试)执行文件的其余部分。

例如,假设以下是 $HOME/.kshrc 的全部内容

#!/usr/bin/env ksh
# this is my kshrc file
KSH_RED="\033[1;31m"
KSH_RESET="\033[00m"
KSH_SENTINEL="${KSH_RED}Hello from KSHRC${KSH_RESET}"

我们可以使用哨兵变量来指示文件是否被执行。您可能需要将上述命令添加到 $HOME/.kshrc 文件中,以便使用后面的代码。或者,您可能希望将上述命令放入 kshrc2 文件中,并对后面的代码进行适当的修改。

假设您的 $HOME/.kshrc 中有上述命令,启动一个新的 Korn shell。让我们在 Korn shell 中以交互方式尝试以下命令:

echo $KSH_SENTINEL
KSH_SENTINEL=""
echo $KSH_SENTINEL

tail -n +2 $HOME/.kshrc > /tmp/kshrc.bash
bash
. /tmp/kshrc.bash
rm /tmp/kshrc.bash
echo $KSH_SENTINEL

上面的内容让我们处于一个交互式 Bourne-again shell 中,其中包含 kshrc 集中的环境变量 KSH_SENTINEL。它还具有来自任何 bashrc 文件集的环境变量,这是我们可能不想要的。我们可以通过在 Korn shell 提示符处执行以下命令,使用 /tmp/kshrc.bash 文件而不是 bashrc 进入 Bourne-again shell:

KSH_SENTINEL=""
tail -n +2 $HOME/.kshrc > /tmp/kshrc.bash
echo "rm -f /tmp/kshrc" >> /tmp/kshrc.bash
bash -rcfile /tmp/kshrc.bash
echo $KSH_SENTINEL

到目前为止,我们已经能够进入交互式 Bourne-again shell 并根据一个非常简单的 kshrc 文件设置环境。我们使用临时文件 /tmp/kshrc.bash 来完成此操作,该文件在第一次获取时已被删除。

当然,bash 可能会因为更复杂的 kshrc 文件中的某些 ksh 语法或命令而卡住。但是,如果我们只是在 kshrc 文件中设置环境变量和创建别名,那么我们应该能够使用到目前为止所做的事情。如果我们只需要执行 kshrc 中与 bash 兼容的部分,我们可以使用注释来描述这些部分。然后,我们可以使用 awk 或其他东西将这些部分复制到 /tmp/kshrc.bash 文件中。

现在让我们编写一个使用这些概念的 Korn shell 脚本(就像最初提出的问题一样)。该脚本在 Korn shell 中启动,从 kshrc 文件中提取命令,附加 bash 命令,执行 kshrc+bash 命令,然后返回到 Korn shell。我们将此 ksh 脚本称为“bash_my_korn.ksh”。这是一个版本

#!/usr/bin/env ksh

#
# Say hello with the print command (ksh only)
print "Hello from $0"

#
# Set a variable for the temporary file
TMP_FILE="/tmp/kshrc.bash"

#
# Unset the sentinel
KSH_SENTINEL=""
print "Korn sentinel is $KSH_SENTINEL"

#
# Assemble the bash script in 2 sections
# Section 1:

print "#!/usr/bin/env bash" > $TMP_FILE
tail -n +2 $HOME/.kshrc >> $TMP_FILE

#
# Section 2 is the bash commands that we want to
# execute after the kshrc commands are executed
cat >> $TMP_FILE <<-EOS

echo "Hello from the Bourne-again shell"

if [[ -z "\$KSH_SENTINEL" ]] ; then
    echo "Bash can NOT see the sentinel variable"
else
    echo -e "Bash can see sentinel \$KSH_SENTINEL"
fi
print "Bash shell does not know the print command"

echo "Goodbye from Bourne-again shell"
EOS

#
# The bash command file now exits.  There are several ways to execute it.
print
print "Method 1, without the bashrc file"
bash --norc $TMP_FILE

print
print "Method 2, requires the script be executable"
chmod u+x $TMP_FILE
$TMP_FILE           # the bash command is on the first line of the script

#
# Now finish the Korn shell script
print
print "Goodbye from $0"

#
# Clean up ?
rm -f $TMP_FILE

希望上面脚本中的注释能够解释它。这个想法是组装一个包含 kshrc 命令和 bash 命令的单个 bash 脚本,然后简单地执行该脚本。示例 ksh 脚本包含一堆打印命令,因此您可以看到正在执行哪些部分。该脚本可以自行删除,但最好让创建该脚本的 Korn shell 也将其删除。

让我发表几点评论。首先,请注意我们可以使用--norc选项启动 bash 以避免执行通常的 bashrc 文件。其次,我们可以cat将命令附加到 bash 脚本中,但是如果 bash 命令包含环境变量,我们需要在美元符号前面放置一个反斜杠,以防止 Korn shell 扩展变量,就像我们上面所做的那样。第三,此演示应被视为概念证明,以帮助您开始开发自己的解决方案。

相关内容