前言

linux新手可能会通过su方式切换用户,但没有意识到环境变量没有切换,导致一些奇葩问题,这里便是一个例子,值得记录。

笔者在切换linux用户使用ZSH时遇到问题,确切来说是切换用户后安装oh-my-zsh时遇到问题。
问题出现的根本原因在切换用户方式上,我是通过su 某用户切换用户,而这样切换用户,环境变量仍是切换前用户的!

关于切换用户环境变量是否随之切换看这里解析。

  • 熟悉linux的朋友:只需看问题,原因,解决办法即可。
  • 新手:可以看下完整解决过程。个人认为,遇到问题->解决问题的过程才是最重要的,知道问题的答案去理解都不难,关键是由不懂到懂的过程。

问题

背景:linux下,zsh已成功安装,某个用户的oh-my-zsh也已成功安装,能正常使用。

可能,你刚新添加了一个用户,想这个用户也能使用zsh;可能你因某个需求要切换到某个用户,切换后发现其shell不是zsh或用起来不方便,想这个用户也能方便使用zsh。总之,你通过su A用户切换到A用户,然后开始

  1. 安装oh-my-zsh,执行指令

    sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
    

    遇到类似以下报错:

    Cloning Oh My Zsh...
    fatal: could not create work tree dir '/root/.oh-my-zsh'.: Permission denied
    Error: git clone of oh-my-zsh repo failed
    
  2. 疑似权限问题,你尝试加sudo解决

    sudo sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
    

    然后报已安装错误

    You already have Oh My Zsh installed.
    You'll need to remove /root/.oh-my-zsh if you want to re-install.
    

原因

首先,明确一点:oh-my-zsh相关文件是每个用户独有的,不是所有用户共用一份的。

  • 第一个报错:

    1. 安装脚本install.sh文件内容:判断$ZSH是否有值,有值,访问其指代的目录文件,没问题则打印你已安装;权限问题访问不了则权限错误;无值,则将相关文件安装在~/.oh-my-zsh,并export ZSH=~/.oh.-my-zsh
    2. 通过su切换用户,环境变量并未随之改变$ZSH变量为切换前用户的对应值,以切换前用户为root为例,echo $ZSH,显示/root/.oh-my-zsh

    综上,当前用户并未安装oh-my-zsh,但安装脚本根据前一个用户的$ZSH以为当前用户已安装,但没权限访问,因此报权限错误。

  • 第二个报错:加上sudo后,有了访问/前一个用户家目录/.oh-my-zsh目录的权限,访问发现确实存在,就报已安装,需要删除后才能重新安装。

综上,根本原因是环境变量没有随用户切换而切换

su 用户 :只切换身份

su - 用户 :身份和shell(包含环境变量)都切换

解决办法

对安装oh-my-zsh来说,关键在于$ZSH变量,只要清空之即可,下面两种方式均可:

  1. 手动清空$ZSH变量

    ZSH=
    ## 查看是否清空成功
    echo $ZSH
    
  2. ctrl + d退回能最开始的用户,通过su -切换

    su - 期望用户
    ## 查看一下
    echo $ZSH
    

然后执行下载安装

sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"

输出以下内容,表示成功

         __                                     __   ____  / /_     ____ ___  __  __   ____  _____/ /_  / __ \/ __ \   / __ `__ \/ / / /  /_  / / ___/ __ \
/ /_/ / / / /  / / / / / / /_/ /    / /_(__  ) / / /
\____/_/ /_/  /_/ /_/ /_/\__, /    /___/____/_/ /_/  /____/                       ....is now installed!Please look over the ~/.zshrc file to select plugins, themes, and options.p.s. Follow us at https://twitter.com/ohmyzsh.p.p.s. Get stickers and t-shirts at https://shop.planetargon.com.

安装成功后,查看$ZSH的值,验证上述说法

echo $ZSH
## 输出
/home/当前用户家目录/.oh-my-zsh

熟悉linux的朋友不用往下看了,很啰嗦的~

解决过程

  1. 首先,我是通过root用户连接到服务器的,安装,使用zsh,oh-my-zsh一切顺利,因某个需求要切换到test用户

    su test,发现没有zsh效果,echo $SHELL,是bash…,原来是忘了修改test用户的默认shell,切换回root用户

    vim /etc/passwd,修改并保存

    test:x:1007:1007::/home/test:/bin/bash
    ## 改为
    test:x:1007:1007::/home/test:/bin/zsh
    
  2. 切换到test用户,echo $SHELL,变为zsh了。然而一点也不方便,并且没有炫酷的终端效果——颜色变化,猜测是没有oh-my-zsh,心想,原来好用的是oh-my-zsh!安装之,一条命令而已

    sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
    

    然后就报权限错误:

    Cloning Oh My Zsh...
    fatal: could not create work tree dir '/root/.oh-my-zsh'.: Permission denied
    Error: git clone of oh-my-zsh repo failed
    
  3. 权限问题,加个sudo看看吧

    sudo sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
    

    提示我test用户不在sudo列表里,不能使用sudo,

    test is not in the sudoers file.  This incident will be reported.
    

    添加之

    su root ## 切换到root用户
    chmod u+w /etc/sudoers ## 添加sudoers文件所属用户的写入权限
    vim /etc/sudoers
    ## 添加如下内容
    test    ALL=(ALL)       ALL
    chmod u-w /etc/sudoers  ## 添加完成删除写入权限,保证安全
    

    再执行一次安装指令。报oh-my-zsh已安装…,额,已安装你倒是让我test用户使用啊…

    You already have Oh My Zsh installed.
    You'll need to remove /root/.oh-my-zsh if you want to re-install.
    
  4. 分析

    难道要删除/root/.oh-my-zsh?,但删除了root用户怎么使用呢?

    首先要确认oh-my-zsh相关文件像指令一样给所有用户共用,还是像配置文件一样每个用户独有?

    • 如果是共用的,不应该默认安装在root家目录下啊(我没改任何配置),其它用户去访问root家目录,即使放开权限能行,始终是不合适的(何况我试过把/root/.oh-my-zsh权限设为777,还是不行)。
    • 得出结论:oh-my-zsh相关文件是每个用户独有的。
    • 结论推导是:在test用户下安装oh-my-zsh,会在test用户家目录添加oh-my-zsh相关文件。

    但现在的确是在test用户下,执行github上oh-my-zsh给的安装指令,却报root家目录下oh-my-zsh相关文件权限错误。难道问题出在安装指令上?安装指令指定了安装到哪个目录吗?

  5. 分析安装指令,上网查得

    sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
    
    • sh命令是shell命令语言解释器,-c指从-c后的字符串读取;

    • $()简单理解是将执行括号里代码得到的结果返回

    • wget是下载 指定url的文件(默认指下载,不打印,与curl相反),-O后接保存到本地的文件名,用-O -表示将文件内容打印,不保存到本地文件

      通过与curl比较,更好理解wget使用,链接

    最终得到的就是执行了install.sh脚本文件,并没有通过安装指令指定文件安装位置。

  6. 分析install.sh脚本

    下载install.sh文件来看看内容吧,shell脚本,也是代码而已。

    wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh
    vim install.sh
    

    太大段就不全贴上来了,根据报错Error: git clone of oh-my-zsh repo failed,在install.sh搜索到

      env git clone --depth=1 https://github.com/robbyrussell/oh-my-zsh.git $ZSH || {printf "Error: git clone of oh-my-zsh repo failed\n"exit 1}
    

    再搜一下,You already have Oh My Zsh installed.,内容如下

      if [ -d "$ZSH" ]; thenprintf "${YELLOW}You already have Oh My Zsh installed.${NORMAL}\n"printf "You'll need to remove $ZSH if you want to re-install.\n"exitfi
    

    都有$ZSH变量!且文件中多次出现$ZSH

  7. 再次分析

    按上面的分析,oh-my-zsh相关文件是每个用户独有的,那么

    • 安装脚本理应根据当前用户是谁,来把相关文件安装到谁的家目录;
    • 如果当前用户已安装,安装脚本能识别出来,要求他删除后才能再次安装。

    经查看,install.sh脚本的内容正是如此,具体到安装脚本通过什么来识别,就是$ZSH变量,如果$ZSH为空,文件内容如下:

      if [ ! -n "$ZSH" ]; thenZSH=~/.oh-my-zshfi## 把ZSH设为环境变量了export ZSH=$ZSH
    

    如果$ZSH有值,则输出已安装,要先删除$ZSH指代的文件才能再次安装。

    到这里,就很明显了,根据报错提示,test用户的$ZSH变量是/root/.oh-my-zsh,查看一下,确实是这样。

    echo $ZSH
    /root/.oh-my-zsh
    
  8. 解决:

清空ZSH变量,执行下载安装命令,安装成功后,查看$ZSH变量

ZSH=
sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
echo $ZSH
## 显示
/home/test/.oh-my-zsh

至此,安装成功,问题解决。

总结

  1. 切换用户

    • su 用户:只切换身份
    • su - 用户:切换身份和shell(保护环境变量)
  2. linux下载安装指令

    • wget:默认只下载,-O 文件名 指定保存文件名,-O -打印文件内容不保存为文件。
    • curl:默认只打印,-O保存为文件
    • 常伴随出现的:sh -c$()
  3. 一点体会:遇到问题,不要躲。

    很早就出现切换用户无法正常使用zsh问题,开始是通过尽量不切换用户来避开它,但到了必须切换时,例如不能通过root用户使用composer…,就很烦,心里不踏实,切换用户后一遇到报错,总会怀疑是否与所切换用户无法正常使用zsh有关。如果总是积累这那么多不确定,往下走,好累!

相关链接

  • linux 中切换用户:su和su -的使用环境变量详解
  • oh-my-zsh下载地址
  • curl和wget的区别和使用

安装oh-my-zsh报错could not create work tree dir '/root/.oh-my-zsh'.: Permission denied的原因解决办法相关推荐

  1. 【已解决】启动Python报错api-ms-win-crt-process-l1-1-0.dll缺失,windows7无法升级,升级补丁打不上的解决办法

    [已解决]启动Python报错api-ms-win-crt-process-l1-1-0.dll缺失,windows7无法升级,升级补丁打不上的解决办法 问题:启动python报错api-ms-win ...

  2. python报错:xml.parsers.expat.ExpatError: not well-formed (invalid token): line 3, column 1的解决办法

    本篇文章主要讲解,python报错:xml.parsers.expat.ExpatError: not well-formed (invalid token): line 3, column 1的解决 ...

  3. 【庖丁解牛】成功解决nginx报错:bind() to 0.0.0.0:8090 failed (13: Permission denied)

    文章目录 错误复现 错误原因 解决方案 错误复现 在nginx设置基于端口的虚拟主机的时候,设定两个端口,一个是80,一个是8090, 在重启nginx的时候 [root@zmedu-17 rpm]# ...

  4. 如何安装kaggle API下载数据 及报错OSError: Could not find kaggle.json. Make sure it‘s located in /home/user/解决办法

    如何安装kaggle API下载数据 及报错OSError: Could not find kaggle.json. Make sure it's located /解决办法 C:\Users\pc& ...

  5. 启动项目,报错:The server selected protocol version TLS10 is not accepted by client preferences [TLS12]解决办法

    使用idea加载刚down下来的项目启动时,报错:The server selected protocol version TLS10 is not accepted by client prefer ...

  6. mysql启动报错: 某些服务在未由其他服务器或程序使用时即将自动停止-解决办法

             第一步:进入到 DOS窗口,按windows+r用管理员登录C:\Windows\system32>是这种操作界面          第二步:E:\>cd E:\mysq ...

  7. Qt编译报错:usr/include/c++/4.9/bits/stl_relops.:67: Parse error at “std“的解决办法

    明明安装了gcc和g++,版本是4.9.2 系统debian8 qmake -v qmake myproject.pro  无任何报错 make 编译没有问题,链接的时候报错: /usr/local/ ...

  8. 加载MNIST报错:[WinError 10060] 由于连接方在一段时间后没有正确答复解决办法(亲测)

    转载:https://blog.csdn.net/landcruiser007/article/details/79346982 tensorflow加载mnist数据集,一些书上和博客中的代码如下: ...

  9. 类中调用界面ActiveX控件报错当前线程不在单线程单元中因此无法实例化 ActiveX 控件的解决办法...

    解决办法是Form类中定义一个静态的ActiveX对象,在formload中将界面上的ActiveX对象赋值给新定义的对象,类中访问该静态对象即可. public static AxClientDri ...

最新文章

  1. pip通过阿里源安装
  2. 用VC写Assembly代码(5) --函数调用(三)
  3. linux qt3编译出错,Linux下编译Qt 5版本源码
  4. show processlis
  5. python图片转excel,Python代码,将图片转为了Excel
  6. plsql 通过 excel 创建表
  7. creo 6.0—02:单位的设置,默认绘图模板的绘制(重点)
  8. 旅行社H5广告宣传怎么做?
  9. 33. Prometheus-报警-通知模板参考
  10. 企业微信预览图片的接口使用wx.previewImage
  11. 用例图(use case diagram)
  12. ssm毕设项目酒店管理系统08281(java+VUE+Mybatis+Maven+Mysql+sprnig)
  13. ubuntu 关闭系统自动更新
  14. 大胆预测一下《数据结构》期末机考题
  15. Vue动画出现和隐藏
  16. 六个办公常用的网站,让你大开眼界的网站
  17. 【厚积薄发系列】C++项目总结19—组件化架构思想
  18. HTML——表单及表单元素
  19. 两道大众点评网技术部的笔试题
  20. intouch的服务器修改密码后,intouch登录设置

热门文章

  1. AutoCAD C# 多段线自相交检测
  2. 安装ttf-mscorefonts-installer的方法
  3. 计算机调剂光学工程,山东大学2020研究生调剂信息-光学工程/材料科学与工程
  4. 两个日期之间的天数--【编程珠玑】
  5. 用1个拨码开关控制所有的LED灯亮灭
  6. mysql添加普通索引_mysql在建表语句中添加索引
  7. IntelliJ Idea 2017 免费激活方法(亲测有效,可以尝试一下)
  8. 「第十二章」Web框架安全
  9. java进行图片合成以及写入自定义字体
  10. ubuntu下搭建android开发环境(四)核心篇安装AndroidStudio、sdk、jdk