【问题标题】:Not working „source ~/.profile“ inside bash script在 bash 脚本中无法使用“source ~/.profile”
【发布时间】:2026-01-07 20:55:01
【问题描述】:

要使用源永久更新 ~/.profile,仅适用于手动输入。整个系统的重启也不会更新~/.profile,我需要手动更新。

是否有一种特殊的代码风格可以将其用作 bash/shell 脚本中的工作代码,或者这种特殊代码不打算在自动化脚本中使用?

需要它来自动安装 golang。

在下面的代码中,“source ~/.profile”行不起作用,并且没有任何错误消息,其余的工作正常:

#!/bin/bash
sudo apt update
sudo apt -y upgrade
cd ~
curl -O https://dl.google.com/go/go1.12.5.linux-amd64.tar.gz
tar xvf go1.12.5.linux-amd64.tar.gz
sudo chown -R root:root ./go
sudo mv go /usr/local
cd ~
sudo rm go1.12.5.linux-amd64.tar.gz
sudo echo "export GOPATH=\$HOME/work" >> ~/.profile
sudo echo "export PATH=\$PATH:/usr/local/go/bin:\$GOPATH/bin" >> ~/.profile
source ~/.profile

【问题讨论】:

  • 如果“手动输入”是指在交互式外壳中 输入,那么问题在于获取文件设置变量/别名/等。 在执行源代码的 shell 中,运行脚本的 shell 与用户的交互式解释器不同。如果相反,“不工作”意味着您收到类似source: command not found 的错误,这意味着您正在使用sh,而您应该使用bash。如果用“不工作”代替,您的意思是没有设置别名,那是因为别名在交互式解释器中默认是关闭的。
  • 但是,我们需要猜测您的意思是许多可能的解释中的哪一个,这意味着这不是一个足够明确的问题,无法回答。
  • 感谢您的回复。我将问题更新为整个脚本。最后一行的执行将不起作用,没有任何错误。似乎它有效,但是,命令“go version”甚至“go”都不会被识别。这个时候golang就不行了。我需要自己打开一个终端并在“source ~/.profile”中输入才能永久工作。
  • 正确 -- source 在你正在运行的 shell 中运行一些东西。在脚本中,它是运行脚本的 shell,不是用户启动脚本的 shell。因此,source ~/.bashrc 在该上下文中将更改 GOPATH 脚本本身,但不会更改启动脚本的用户...因为您在脚本退出之前就这样做了,在脚本自己的环境中改变任何东西都不是很有用。
  • 你为什么要sudo echo 一个字符串?通常echo 不需要任何特殊权限。您也不需要sudo 来删除您自己下载的文件,返回几个命令。

标签: linux bash shell ubuntu go


【解决方案1】:

首选:

获取脚本本身而不是运行它 - 然后脚本中的命令在 当前 shell 中运行,包括 source ~/.profile

另一种方式(由于这个替换了正在运行的shell,历史、变量值和其他状态都会丢失。所以应该有一个非常很好的理由使用这个方法):

使用exec bash 或类似的东西而不是source ~/.profile - 这会用另一个实例替换当前运行的 Bash,该实例本身将加载新的.profile

【讨论】:

  • 鉴于这会丢弃 OP 原始外壳中的所有其他状态,因此它是一个非常大的锤子。如果运行一些随机程序将我留在一个新的交互式 shell 中,除了我的 dotfiles 中定义的函数/变量/等之外没有任何活动的函数/变量/等,我会感到非常惊讶和沮丧。
  • @CharlesDuffy:是的。我会在我的回答中注明。
【解决方案2】:

这是一个重构,它将决定权交给用户并在一定程度上清理了脚本。

#!/bin/bash
# Put this in a variable so there is only one place to update
tarball='go1.12.5.linux-amd64.tar.gz'
sudo apt update
sudo apt -y upgrade
# cd || why would you?
curl -O "https://dl.google.com/go/$tarball"
tar xvf "$tarball"
sudo chown -R root:root ./go
sudo mv go /usr/local
rm "$tarball"
printf '%s\n' "export GOPATH=\$HOME/work" \
       "export PATH=\$PATH:/usr/local/go/bin:\$GOPATH/bin" >> ~/.profile
echo "$0: done. source ~/.profile or exec bash to activate new settings." >&2

【讨论】:

  • 其实还是不建议在脚本中使用apt-get 而不是apt
  • 感谢细化,比较好,但没有解决问题。即使我启动一个新终端,或者在执行安装脚本后重新启动整个计算机,golang 也不会被识别,直到我手动输入“source ~/.profile” - 我需要考虑的其他建议。我在 bash/shell 脚本方面的技能目前还不是很深。
  • 如果您在登录时没有读取 .profile,您的 Bash 配置会以其他有趣的方式受到影响。