/etc/profile.d中的脚本被忽略?


61

我是Ubuntu的新手。我正在运行13.10桌面。

我想设置一些系统范围的别名和bash的自定义提示。我发现这篇文章:

https://help.ubuntu.com/community/EnvironmentVariables

按照本文的建议,我创建了/etc/profiles.d/profile_local.sh。它由root拥有,并且与那里的其他脚本一样具有644的权限:

root@ubuntu:/etc/profile.d# ll
total 28
drwxr-xr-x   2 root root  4096 Mar 23 08:56 .
drwxr-xr-x 135 root root 12288 Mar 23 09:15 ..
-rw-r--r--   1 root root   660 Oct 23  2012 bash_completion.sh
-rw-r--r--   1 root root  3317 Mar 23 07:36 profile_local.sh
-rw-r--r--   1 root root  1947 Nov 23 00:57 vte.sh

我进一步确认了/ etc / profile调用/etc/profile.d。它包含以下代码块:

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

登录后,似乎没有获得我创建的自定义脚本profile_local.sh的来源。但是,如果登录后我“获取/etc.profile.d/profile_local.sh”,则得到预期的行为,自定义别名和自定义提示。

我究竟做错了什么?

脚本“ profile_local.sh”的内容:

# 3/23/14 - Copied from Gentoo /etc/bash/bashrc
# Placed in /etc/profile.d as described at:
# https://help.ubuntu.com/community/EnvironmentVariables

# This file is sourced by all *interactive* bash shells on startup,
# including some apparently interactive shells such as scp and rcp
# that can't tolerate any output.  So make sure this doesn't display
# anything or bad things will happen !


# Test for an interactive shell.  There is no need to set anything
# past this point for scp and rcp, and it's important to refrain from
# outputting anything in those cases.
if [[ $- != *i* ]] ; then
        # Shell is non-interactive.  Be done now!
        return
fi

# Bash won't get SIGWINCH if another process is in the foreground.
# Enable checkwinsize so that bash will check the terminal size when
# it regains control.  #65623
# http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11)
shopt -s checkwinsize

# Enable history appending instead of overwriting.  #139609
shopt -s histappend

# Change the window title of X terminals 
case ${TERM} in
        xterm*|rxvt*|Eterm|aterm|kterm|gnome*|interix)
                PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\007"'
                ;;
        screen)
                PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\033\\"'
                ;;
esac

use_color=false

# Set colorful PS1 only on colorful terminals.
# dircolors --print-database uses its own built-in database
# instead of using /etc/DIR_COLORS.  Try to use the external file
# first to take advantage of user additions.  Use internal bash
# globbing instead of external grep binary.
safe_term=${TERM//[^[:alnum:]]/?}   # sanitize TERM
match_lhs=""
[[ -f ~/.dir_colors   ]] && match_lhs="${match_lhs}$(<~/.dir_colors)"
[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(</etc/DIR_COLORS)"
[[ -z ${match_lhs}    ]] \
        && type -P dircolors >/dev/null \
        && match_lhs=$(dircolors --print-database)
[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true

if ${use_color} ; then
        # Enable colors for ls, etc.  Prefer ~/.dir_colors #64489
        if type -P dircolors >/dev/null ; then
                if [[ -f ~/.dir_colors ]] ; then
                        eval $(dircolors -b ~/.dir_colors)
                elif [[ -f /etc/DIR_COLORS ]] ; then
                        eval $(dircolors -b /etc/DIR_COLORS)
                fi
        fi

        if [[ ${EUID} == 0 ]] ; then
                PS1='\[\033[01;31m\]\h\[\033[01;34m\] \W \$\[\033[00m\] '
        else
                PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
        fi

        alias ls='ls --color=auto'
        alias grep='grep --colour=auto'
else
        if [[ ${EUID} == 0 ]] ; then
                # show root@ when we don't have colors
                PS1='\u@\h \W \$ '
        else
                PS1='\u@\h \w \$ '
        fi
fi

# Try to keep environment pollution down, EPA loves us.
unset use_color safe_term match_lhs

TZ="PST8PDT"

alias ll='ls -la'
alias dig='dig +search'
alias dir='ls -ba'

alias edit="ee"
alias ss="ps -aux"
alias dot='ls .[a-zA-Z0-9_]*'
alias news="xterm -g 80x45 -e trn -e -S1 -N &"

alias more="less"
alias c="clear"
alias m="more"
alias j="jobs"

# common misspellings
alias mroe=more
alias pdw=pwd

1
不,它不是可执行文件,其他两个脚本也不是。但是我改变了它,然后再试一次。仍然没有运气。
Drew

3
这与添加.sh无关,无关紧要,无论如何,其中的文件profile.d都是源文件,不会执行,这稍有不同,并且不需要文件可执行。这里的问题profile是非登录脚本不会读取&co。
terdon

1
提请读我的答案。非登录外壳会忽略配置文件,但是Ubuntu的默认GUI登录将读取其中的一些。只需使用.bashrc,您所有的问题都将消失。还有一个优先级问题,如果随后读取的文件之一也设置了PS1,则先前的值将被丢弃。无论如何,认真地,不要触摸文件管理器中的文件管理器,不要/etc与主目录中的文件管理器玩耍,并且.bashrc不要使用个人资料。
terdon

1
是的,那应该是一个登录shell(如果您下次应该在问题中包含该内容,则为这种类型)。但是,大多数系统.profile在您的家中都有默认文件,并且那里的设置将覆盖您在中所做的任何操作/etc/profile。除非您知道自己在做什么,否则基本上不要触摸/etc。这就是用户特定文件的用途。另外,请编辑您的问题并确切说明您的连接方式,这将改变一切。
terdon

4
请不要使用/etc/profile.d那是一个非常糟糕的主意,并且会影响系统的所有用户。只是包括命令,从profile_local.sh你的~/.profile或者干脆加入这一行到你的源脚本~/.profile. /path/to/profile_local.sh。(.意味着source,它将读取您提供的文件并运行在那里找到的命令)。
terdon

Answers:


108

要了解这里发生的情况,您需要了解一些有关如何运行shell(在本例中为bash)的背景信息。

  • gnome-terminal例如,当您打开一个终端仿真器时,您正在执行的是交互式非登录外壳程序。

  • 当您通过命令行从命令行登录计算机时ssh,或者运行诸如之类的命令su - username,则您正在运行交互式登录外壳程序。

  • 当以图形方式登录时,您将运行完全不同的内容,详细信息将取决于您的系统和图形环境,但通常是由图形外壳来处理您的登录。虽然许多图形化shell(包括Ubuntu默认值)都/etc/profile不会全部读取。

  • 最后,当您运行shell脚本时,它会在非交互式非登录shell中运行

现在,bash启动时将读取的文件取决于其运行时所使用的shell类型。以下是man bash(强调我的)“ INVOCATION”部分的节选:

当bash作为交互式登录shell或使用--login选项作为非交互式shell 调用时,它首先从文件/ etc / profile(如果存在)读取并执行命令。读取该文件后,它将按此顺序查找〜/ .bash_profile,〜/ .bash_login和〜/ .profile,并从存在且可读的第一个命令中读取并执行命令。启动外壳程序时,可以使用--noprofile选项来禁止此行为。

当 启动非登录外壳程序的交互式外壳程序时,bash会从/etc/bash.bashrc〜/ .bashrc中读取并执行命令(如果这些文件存在)。使用--norc选项可以禁止这种情况。--rcfile file选项将强制bash从文件而不是/etc/bash.bashrc和〜/ .bashrc中读取并执行命令。

这意味着您正在编辑错误的文件。您可以通过删除使用虚拟控制台测试此Ctrl+ Alt+ F2(与返回到GUI Alt+ F7,或F8根据您的设置),并在那里登陆。您将看到提示和别名可用。

因此,为了将要应用的设置应用于非登录外壳,即每次打开终端时所获得的类型,都应该~/.bashrc改为对其进行更改。另外,您也可以将别名放置在文件中~/.bash_aliases(但是,请注意,这是Ubuntu功能,您不应期望它可在其他发行版上使用)。

有关应使用哪个文件的更多详细信息,请参见此处


笔记:

  • Debian(扩展名为Ubuntu)也具有默认~/.profile来源~/.bashrc。这意味着您所做的任何更改~/.bashrc也将被登录Shell继承,但i)并非在所有Linux / Unix计算机上都是如此,并且ii)并非如此,这就是为什么通常应该始终使用~/.bashrc&co而不是~/.profileor的原因/etc/profile

  • 另外,关于用法的一般说明和对配置文件的更改/etc将影响所有用户。这通常不是您想要执行的操作,应避免使用。您应该始终在主目录(~/)中使用等效文件。

  • 依次读取各种配置文件。具体来说,对于登录shell,顺序为:

    /etc/profile -> /etc/profile.d/* (in alphabetical order) -> ~/.profile

    这意味着中的任何设置都~/.profile将覆盖先前文件中的所有设置。


1
根据这篇博文howtolamp.com/articles/…,您还可以echo $0从终端运行,如果输出以“-”为前缀,则您位于登录shell中。
stackoverflower

@stackoverflower不在我的系统上。这适用于远程交互式登录外壳。跑步时似乎没有bash -l。无论如何,这为什么有意义?问题不在于如何检查正在运行的外壳类型。
terdon

宏伟的帖子,想知道当我遇到同样的问题时,为什么它没有出现在Google
Donato

@stackoverflower如果"$0"扩展为以开头的内容-,则说明您具有登录shell。但是相反的情况是不正确的:缺少-不能确保您不在登录外壳中。启动登录Shell的最常见方法确实可以带给您领先-,但并非全部。man bash告诉我们登录shell是一个参数为零的第一个字符为-或以--login选项开头的登录shell。” -l是的简写形式--login它们等效。)在Bash中,您可以运行shopt login_shell进行检查。
伊莱亚·卡根

2

另一种可能性,尤其是像历史设置设置HISTSIZEHISTFILESIZEHISTCONTROL,并且PS1是该文件被加载,但设置在另一个文件是源后覆盖,最可能的罪魁祸首是~/.bashrc。(我为我们的服务器设置了一组默认设置,例如提示为红色的root来警告用户和带有时间戳的大量历史记录)

默认的Ubuntu .bashrcfrom /etc/skel设置了几个设置,从某个地方进行设置可能会很有意义,即它不会覆盖/etc/profile.d(Like /etc/bash.bashrc)系统所有者设置的设置(如果用户对其进行了编辑.bashrc,则可以覆盖系统默认文件设置)更烦人)


2

在Debian的终端会话中,我为所有用户解决了这个问题,所以:

添加到

sudo nano /etc/bash.bashrc

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

/etc/profile

1

遵循以下路径:

  • 打开编辑->首选项
  • 在第一个标签“常规”中的标签“命令”下,启用“将命令作为登录外壳运行”

-1

VERSION =“ 16.04.3 LTS(Xenial Xerus)”

好的,所以每个人都假设这里的人不希望所有用户都使用/etc/profile.d/somefile.sh,但就我而言,这正是我想要的。

因此,实际上,在使用Ubuntu的情况下,如果要使用它并希望它在图形shell中生效,您要做的就是设置文件,然后注销并再次登录。现在,所有控制台或您启动的任何内容(无论是xterm类型还是控制台类型(或放置到外壳中))都将具有该文件的来源。

无需为所有用户使用.bashrc等。抱歉,以上答案尚不清楚。他们说的一切都是正确的,但实际上大多数情况都不是正确的,因为Windows Manager启动的所有内容都会继承这些设置,因此只要您打算将其应用于所有用户,只需重新登录并解决您的问题,就不必理会.bashrc等。 。


2
我的问题恰恰是在图形用户界面下运行的终端中不会发生这种情况。在Ubuntu 16.04.3或18.04中都没有。
Thomas Arildsen '18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.