1 windows脚本配置环境变量
一般我们采用setx命令来设置环境变量,加上/m
参数是设置系统环境变量,需要管理员权限;不加则设置当前用户的用户环境变量。设置一些独立变量的时候,如JAVA_HOME、MAVEN_HOME等,我们可以很容易在bat脚本中判断这些环境变量是否存在和重写这些变量的值。但是,PATH变量的修改却没这么简单。PATH添加一个分量是容易的,如果不加判断,PATH变量重复添加了路径,无意义的增加了长度。配置PATH的时候,用户采用绝对路径,或在其中用变量替代,如%JAVA_HOME%\bin,我们通过%PATH%获取得值都是绝对路径的形式。当我们想向PATH添加%JAVA_HOME%\bin这个分量的时候,该如何不重复添加需要进一步思考。
现在以PATH添加%JAVA_HOME%\bin为例,思考如何操作。
首先,我们判断PATH中是否存在"%JAVA_HOME%\bin"。注意这里判断原字符,而不是解译为绝对路径的。存在,说明我们不需要重复添加了,在你修改JAVA_HOME后,这个变量自然是你预期的。不存在则需要进一步判断:可能用户之前采用bin的绝对路径;可能就是没有配置。我们可以通过查找%PATH%是否包含修改之前的%JAVA_HOME%\bin的绝对路径来判断,查找到说明是前者,我们将查找到这个路径剔除掉,替换为"%JAVA_HOME%\bin"即可,没有查找到更简单,直接添加这个路径即可。因此,在修改JAVA_HOME前,我们可以用一个临时变量记录。下面整理一下,用伪代码的形式
set PRE=%JAVA_HOME%
set JAVA_HOME=newVal
#用[PATH]表示PATH未转为绝对路径的原值
if [PATH] contains "%JAVA_HOME%\bin"
do nothing
else
#判断PATH是否存在原绝对路径
if %PATH% contains %PRE%\bin
#将%pre%\bin替换为"%JAVA_HOME%\bin"
PATH.replace(%PRE%\bin, %JAVA_HOME%\bin)
else
#直接追加到PATH
set PATH="%JAVA_HOME%\bin";%PATH%
关于原样输出PATH,不被转为路径,使用wmic命令解决,网上查找资料多是这个方案。下面是bat实现查找原样PATH有无"%JAVA_HOME%\bin"的真实代码,判断%PATH%是否包含bin的绝对路径也可参考该示例代码。
::记录原JAVA_HOME
set PRE_JAVA_HOME=%JAVA_HOME%
::path原样记录输出到临时文件
wmic ENVIRONMENT where "name='path' and username='<system>'" get VariableValue | more>path_temp.txt
::srcpath变量记录原始的path
for /f "skip=1 delims=" %%a in (path_temp.txt) do (
set srcpath=%%a
goto :flag_1
)
:flag_1
::echo %srcpath%
find "%%JAVA_HOME%%\bin" path_temp.txt>nul
if %errorlevel% equ 0 (
::已存在do nothing
echo "PATH已存在%%JAVA_HOME%%\bin"
) else (
::继续根据PRE_JAVA_HOME和%PATH%判断
::下面可以将%PATH%输出到临时文件,同样采用find命令查找
::略...
)
del path_temp.txt
2 linux脚本配置环境变量
linux配置环境变量的文件有几个,脚本只管将配置写到/etc/profile即可,如果存在其他文件覆盖系统配置,例如用户目录下的.bash_profile,这种情况不是问题,用户环境变量本来就是覆盖系统变量的。
还是以常见的配置JAVA环境变量为例。我们可以通过向文件末尾追加的方式添加我们的环境变量。但是这样多次会使文件内容无意义变长。如果我们自己写自动添加环境变量的脚本,可以采用添加一些特殊的注释作为标记。每次添加前查找特殊注释,如果有采用替换的方式,没有采用追加的方式。下面是示例脚本。
#找到特殊的首尾注释行号,配置夹在其中
startL=$(sed -n -e "/###>>>/=" /etc/profile)
endL=$(sed -n -e "/###<<</=" /etc/profile)
function setEnv(){
if [ "$startL" == "" ]
then
#未找到标记,直接追加
sed -i '$a ###>>>自动添加的配置模块,请勿轻易删除该模块注释和其间的配置' /etc/profile
sed -i '$a export JAVA_HOME='/usr/local/jdk' /etc/profile
sed -i '$a export PATH=\$JAVA_HOME/bin:\$PATH' /etc/profile
sed -i '$a export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib' /etc/profile
sed -i '$a ###<<<自动添加的配置结束' /etc/profile
else
#找到了标记删除标记间的内容,并在原来的行追加
sed -i $startL','$endL'd' /etc/profile
let startL--
sed -i $startL'a ###>>>自动添加的配置模块,请勿轻易删除该模块注释和其间的配置' /etc/profile
let startL++
sed -i $startL'a export JAVA_HOME='/usr/local/jdk' /etc/profile
let startL++
sed -i $startL'a export PATH=\$JAVA_HOME/bin:\$PATH' /etc/profile
let startL++
sed -i $startL'a export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib' /etc/profile
let startL++
sed -i $startL'a ###<<<自动添加的配置结束' /etc/profile
fi
}
setEev
当然,这段脚本肯定需要root权限执行,脚本最前面做个判断吧
has_root() {
if [[ $EUID -ne 0 ]]; then
echo "权限需要提升:该安装程序必须由root或sudo执行" 1>&2
exit 1
fi
}
has_root