当前位置: 首页 > 科技观察

如何理解Linux-Unix登录脚本

时间:2023-03-21 20:15:43 科技观察

不知道大家有没有遇到过这样的场景,当你需要设置一个环境变量,或者运行一个程序来设置你的shell或者桌面环境,但是却没有知道哪里是最方便设置的位置。有一些常见的情况,比如从Debian的包管理程序到IaaS管理,很多任务都需要设置环境变量才能正常运行。有时一个程序通常只需要在第一次登录时运行一次,比如xrandr命令。此外,还有一些程序偶尔会注入到shell中,例如rbenv、rvn或SitePoint自己的envswith程序。让我们看一下DebianGNU/LinuxJessie安装中出现的一些常见选项,并尝试理解它们。/etc/profile默认情况下,Debian提供了/etc/profile文件,用于设置$PATH变量($PATH通常用于声明命令的搜索路径),可以立即生效。下面的代码是/etc/profile的一部分。if["`id-u`"-eq0];thenPATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"elsePATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"fiexportPATH为方便起见,根用户(ID为0)的路径与任何其他用户不同。这是因为系统二进制目录(sbin目录)位置传统上被保留为系统管理程序,或者必须以root身份运行的程序。games路径省略了root用户,因为除非非必要,否则绝对不可能使用root用户来运行游戏程序。接下来,/etc/profile处理$PS1变量的设置,该变量用于设置主要提示字符串(即用户登录时显示的字符)。除了系统shell是Bash外,系统$PS1变量默认设置为$(root用户默认为#)。如果系统的shell使用Bash,/etc/bash.bashrc文件将替换$PS变量来处理主要提示字符串(特殊情况除外)。关于/etc/bash.bashrc稍后我们将简要讨论。所以从这一点上,我们可以推断/etc/profile会在登录时被所有的shell读取(例如,使用login命令)。/etc/profile调用id命令来读取用户ID,而不是使用更高效的Bash内置变量${UID}。Bash使用特定于源的配置而不是定义花哨的shell提示符,因为Bash支持反斜杠转义的特殊字符,例如\u(用户名)和\h(主机名),而许多其他shell不支持此定义。/etc/profile应该尽量与POSIX兼容,以便它与用户可能自己安装的任何shell兼容。DebianGNU/linux通常预装了Dash,这是一个基本的shell,专为实现POSIX(和一些Berkeley)扩展而设计。如果我们修改/etc/profile(修改前备份)为PS1='$'行设置不同的值,然后模拟Dash登录(通过dash-l命令),我们可以看到Dash将使用我们的自定义提示。但是,如果我们调用不带-l参数的dash命令,dash将不会读取/etc/profile。此时Dash会使用默认值(也就是说此时PS1的值就是我们修改之前的值)。关于/etc/profile最后一个有趣的事情是以下代码片段:if[-d/etc/profile.d];thenforiin/etc/profile.d/*.sh;doif[-r$i];then。$ifidoneunsetifi换句话说,任何匹配/etc/profile.d/*.sh的可读内容将被用作变量源。这非常重要,因为它表明实际上永远不需要直接编辑/etc/profile(因此恢复您以前的备份)。上面定义的任何变量都可以在单独的文件中配置,然后覆盖/etc/profile中的设置。这样做的好处是可以在系统升级时,自动将相应的修改添加到/etc/profile文件中。因为Debian的Apt包管理系统通常不会修改默认的配置文件。~/.bash_profile、~/.bash_login和~/.profile/etc/profile的一个潜在问题是它位于系统范围的路径中。这意味着修改它会影响该系统上的所有用户。在个人计算机上,这可能不是什么大问题,但修改它也需要root权限。由于这些原因,每个单独的Bash用户帐户都可以创建~/.bash_profile、~/.bash_login和~/.profil中的任何一个作为Bash配置文件的来源。按照列出的顺序找到的第一个文件将用作配置文件,其余的将被忽略。其他shell,例如Dash,支持类似的东西,但只查找~/.profile文件。这允许用户为特定于Bash的用例配置一个单独的.bash_profile文件,如果在某些时候有必要切换到Dash或另一个shell作为登录shell(例如通过chsh-sdash命令)。您可以保留~/.profile作为这些shell的配置文件。要记住的一件事是默认的Debian框架目录(/etc/skel,用于将文件和目录复制到新用户帐户的主目录)包含.profile文件,但不包含.bash_profile和.bash_login文件。此外,Debian使用Bash作为默认shell,因此许多Debian用户习惯于将他们的Bash登录shell设置放在.profile文件中。看过一些项目的安装说明,比如RVN。本项目建议用户创建.bash_profile文件,但这样做非常危险。根据上面提到的知识,我们知道这会改变用户的shell环境。即使用户不修改.profile文件,也可以利用默认的~/.profile特性,将~/bin添加到$PATH环境变量中。可以提高安全性的一种选择是在创建用户帐户之前将.bash_profile作为指向.bash_rc的符号链接放置在/etc/skel目录中。如果我们查看DebianJessie的默认.profile脚本,我们可以看到以下片段:#ifrunningbashif[-n"$BASH_VERSION"];then#include.bashrcifitexistsif[-f"$HOME/.bashrc"];然后."$HOME/.bashrc"fifi这和我们在/etc/profile中看到的类似。如果shell是Bash,并且找到/etc/bash.bashrc文件,那么/etc/bash.bashrc文件将作为Bash的配置文件。其重要性将在下一节中讨论。Bash在启动时同时读取/etc/bash.bashrc和~/.bashrc,但只有当Bashshell作为交互式shell而不是登录shell启动时(意思是通过xtem启动),才会遵循这个顺序,这是BashShell的标准行为。但是,Debian分别从/etc/profile和~/.profile登录脚本获取配置文件。这显着改变了行为,因此/etc/bash.bashrc和.bashrc(如果存在)总是在Bash启动时被调用,无论它是否是登录shell。不要期望这在各个发行版中都是一样的。.bashrc是添加命令别名的好地方,事实上,有些用户有太多别名,他们更喜欢将它们全部保存在一个文件中。Debian的默认.bashrc查找.bash_alias文件,如果存在,则将其用作别名配置的来源。所以你可以自由地在这个文件中保留你所有的Bash别名。如果用户愿意,.bashrc文件也是用户覆盖$PS1或$HISTSIZE等shell变量的绝佳位置。Debian的默认.bashrc有超过100行,但仍然非常易读且注释很好。顾名思义,.bashrc不是其他非Bashshell配置文件的来源。~/.xsession和~/.xsessionrc如果你是GNU/Linux桌面用户,通过显示管理器本地登录(而不是通过getty登录程序),/etc/profile和~/.profile将无法按预期工作工作。一些显示管理器,例如Gnome显示管理器,简单地将这些文件视为不正确的配置文件。但其他一些显示管理器(如LightDm)却没有。幸运的是,您还有一些其他选择。当启动X窗口系统会话时(使用显示管理器或从虚拟终端使用startx),/etc/X11/Xsessionshell脚本将被执行。这基本上等同于调用/etc/profile的登录shell。这个只对XWindow有效,不作为源配置文件,直接执行。但是也比较复杂,类似于/etc/profile如何从/etc/profile.d目录下的脚本中读取配置,如何从/etc/X11/Xsessions脚本中读取/etc/X11中的配置/Xsession.d/目录读取配置。/etc/X11/Xsession.d目录中的所有脚本名称都以数字开头,因此所有脚本都将按数字顺序读取。DebianJessie包含一个名为40×11-common_xsessionrc的文件。该文件的作用是检查~/.xsessionrc是否可读,如果是,则将其用作配置文件的来源。这使得~/.xsessions成为加载环境变量或运行一次性程序(如xrandr或xmodmap)的完美位置(仅适用于X会话)。如果您愿意,也可以获取/etc/profile或~/.profile。然后任何指定的环境变量也将被您的会话管理器继承(如果尚未继承)。注意.xsessionrc默认是不存在的,需要自己创建这个文件。如果我们继续浏览/etc/X11/Xsession中的文件,我们会发现50×11-common_determine-startup决定加载哪个会话管理器。如果~/.xsessions文件存在且可执行,它将被保存并随后作为99×11-common_start的一部分执行。当~/.xsession用于运行会话管理器时,X会话将被注销。当脚本终止时,您将返回到显示管理器登录屏幕。和~/.xsessionrc类似,~/.xsession默认是不存在的,需要的时候可以创建一个。您可以创建一个简单的.xsession脚本,如下所示#Startoursessionmanagerofchoice。#execx-session-manager其中x-session-manager默认为通过update-alternatives命令配置的任何内容,因此您可以轻松更改系统范围默认会话管理器,只需将x-session-manager替换为/usr/bin/startfce4(切换到XFCE),其他用户帐户完全不会受到影响。当然,许多显示管理器提供了直接从登录屏幕选择通用会话管理器的功能,因此通常不需要此文件。然而.xsession提供了更大的灵活性,您可以使用任何程序调用此文件,而不仅仅是会话管理器。例如,在这里您可以在while循环中调用chromium或iceweasel,而不是进行基本的kiosk模式设置。~/.bash_logout我们之前介绍了用户运行交互式Bash登录shell时读取的文件,但是如果您想在注销后保持程序运行怎么办?对于这个用例,~/.bash_logout文件派上用场了。Debian中的默认配置仅用于清除屏幕(我认为从安全的角度来看这很重要),但可以想象以下内容可以用于其他目的,例如,为少数人显示屏幕离开机器前几秒时钟提醒。主要限制因素是.bash_logout仅在注销交互式shell时读取,并且不能假设在注销X会话时加载。其他选项以上内容涵盖了大多数常见选项。根据您的安装环境(例如/etc/environment),可能存在其他选项,但我认为它们可能不存在于其他平台上,并且几乎不需要接触它们。示例那么,您应该将系统范围的环境变量放在哪里?如果你想让一个环境变量影响所有用户,/etc/profiled./someifle.sh会是一个不错的选择。但是,这假设您正在使用以/etc/profile作为配置源的登录管理器。如果没有,您可以(作为管理员)将脚本添加到/etc/X11/Xsession.d/以替换/etc/profile作为配置源。如果你想要一个可以找到私有目录路径并将其添加到你的PATH中的脚本,你需要考虑这个目录是否会移动很多东西。如果您将代码添加到.profile以实现此目的,则用户需要注销并重新登录。在用户会话期间更改PATH。如果将代码添加到.bashrc中,则意味着每次用户打开xterm时都会执行代码,如果花费的时间超过半秒,则可能不太理想。所以这是一个权衡的问题。如果您只想为您的个人登录会话设置一个环境变量,并且它只关心X会话,您可以将它添加到~/.xsessionrc。这样做的好处是它通常可用于通过X会话管理器启动的所有程序,因为它是在X会话管理器启动之前设置的,并且是继承的。例如,某些图形驱动程序可以通过运行exportvblank_mode=0来禁用垂直同步。因此位于.xsessionrc中的变量会影响所有程序。但是,如果将此行添加到.bashrc中,则只有通过xterm登录的程序会受到影响。通过窗口管理器启动的程序照常运行。您可以将其添加到.profile并从.xessionrc获取.profile。但是,当您的X服务未运行时,您不需要导出环境变量。希望您现在对登录和注销脚本如何在DebianGNU/Linux系统上工作有了更好的理解。如果您创建了这些登录和注销脚本,或者遇到了任何特别有趣或创新的用途,请在评论中告诉我们您是如何做到的。在本系列的下一部分中,我们将讨论点文件管理选项。