![Bash - 在脚本中更改主机名后,PS1 未使用正确的主机名进行更新](https://linux22.com/image/74313/Bash%20-%20%E5%9C%A8%E8%84%9A%E6%9C%AC%E4%B8%AD%E6%9B%B4%E6%94%B9%E4%B8%BB%E6%9C%BA%E5%90%8D%E5%90%8E%EF%BC%8CPS1%20%E6%9C%AA%E4%BD%BF%E7%94%A8%E6%AD%A3%E7%A1%AE%E7%9A%84%E4%B8%BB%E6%9C%BA%E5%90%8D%E8%BF%9B%E8%A1%8C%E6%9B%B4%E6%96%B0.png)
这是我来自 stackoverflow 的帖子的副本;我意识到我应该在这里问...
我想运行一个更改主机名的脚本,并使用正确的主机名立即更新我的 bash 提示符(PS1 变量)。我怎样才能做到这一点?
我运行这个
#!/bin/bash
# Usage: ./changehost <newhostname>
#Do two sed's to edit the files for persistent hostname change
sed -i s/$(hostname)/$1/g "/etc/hosts"
sed -i s/$(hostname)/$1/g "/etc/sysconfig/network"
#run the hostname command with new hostname to update it
hostname $1
在这样的终端中得到这个
[user@host dir]# ./changehost newhostname
[user@host dir]#
但我想要的是这个
[user@host dir]# ./changehost newhostname
[user@newhostname dir]#
仅当我打开新的外壳时,终端才会正确更新。
我也尝试过这样做
export PS1='somestring'; export PS1='[\u@\h \W]\$'
在终端的脚本之外,它确实切换到“somestring”并返回,但主机名保持不变。 :\
是否有可能进程开始时\h就存储在内存中并且启动后无法更改?
答案1
如果您的 PS1 类似于:
export PS1='[\u@\h \W]\$'
\h 的值仅在 bash 启动时设置。因此,如果更改主机名,则需要启动一个新的 bash 实例:
exec bash
将用新实例替换 bash(更新 \h 的值)。遗憾的是,它将退出正在运行的脚本。需要一些其他的魔法来对主机名更改后执行代码的 shell 脚本进行更改。我认为不可能使用更新的主机名和\h
.但我也相信这不是你所要求的。
答案2
两个问题
PS1 设置一次,主机名更改后必须重新设置。
您可以使用以下命令编辑脚本
export PS1='[\u@'$(hostname)' \W]\$'
最后,但脚本应该运行为
. ./changehost newhostname
注意前导点。
如果不使用前导点,PS1 将被设置在新的临时 shell 中并丢失。
目前尚不清楚 bash 在运行后是否会更新主机名(用户名)值(存储在 /h、/u 中),因为这些值不太可能更改。
然而 bash 会照顾 PATH。
答案3
没有办法让 Bash 更新\h
被翻译成的值。启动时读取一次,之后不再修改。因此,如果您需要获取更新的提示,唯一的选择是:
- 启动一个子shell —
bash
- 用新的 shell 替换当前的 shell —
exec bash
- 更新 PS1,替换
\h
为$(hostname)
或 文字字符串
现在,更多地了解 Bash 内部结构。主机名值保存在current_host_name
变量中,该变量在中定义shell.h:113
:
extern char *current_host_name;
它用在三个地方variables.c:695
:
temp_var = set_if_not ("HOSTNAME", current_host_name);
parse.y:6039
:
case 'h':
case 'H':
t_host = savestring (current_host_name);
if (c == 'h' && (t = (char *)strchr (t_host, '.')))
...
和y.tab.c:8333
:
case 'h':
case 'H':
t_host = savestring (current_host_name);
if (c == 'h' && (t = (char *)strchr (t_host, '.')))
...
shell_initialize()
并且在以下函数中仅为其赋值一次(除了用空字符串初始化之外)shell.c:1918
:
/* It's highly unlikely that this will change. */
if (current_host_name == 0)
{
/* Initialize current_host_name. */
if (gethostname (hostname, 255) < 0)
current_host_name = "??host??";
else
current_host_name = savestring (hostname);
}
所有行号和文件名均来自源bash-5.1.tar.gz
代码kernel.org 上的镜像。
答案4
看起来 bash 没有在每个提示显示上读取当前主机名,因此您需要告诉 bash 重新读取它。您可以尝试:
PS1=$PS1
或者
. ~/.bashrc