你可能不知道的shell、bash二三事(Centos 7)

个人.bashrc:

~/.bashrc:

# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

 

全局bashrc:

/etc/bashrc:

# /etc/bashrc

# System wide functions and aliases
# Environment stuff goes in /etc/profile

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

# are we an interactive shell?
if [ "$PS1" ]; then
  if [ -z "$PROMPT_COMMAND" ]; then
    case $TERM in
    xterm*|vte*)
      if [ -e /etc/sysconfig/bash-prompt-xterm ]; then
          PROMPT_COMMAND=/etc/sysconfig/bash-prompt-xterm
      elif [ "${VTE_VERSION:-0}" -ge 3405 ]; then
          PROMPT_COMMAND="__vte_prompt_command"
      else
          PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
      fi
      ;;
    screen*)
      if [ -e /etc/sysconfig/bash-prompt-screen ]; then
          PROMPT_COMMAND=/etc/sysconfig/bash-prompt-screen
      else
          PROMPT_COMMAND='printf "\033k%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
      fi
      ;;
    *)
      [ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-default
      ;;
    esac
  fi
  # Turn on parallel history
  shopt -s histappend
  history -a
  # Turn on checkwinsize
  shopt -s checkwinsize
  [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
  # You might want to have e.g. tty in prompt (e.g. more virtual machines)
  # and console windows
  # If you want to do so, just add e.g.
  # if [ "$PS1" ]; then
  #   PS1="[\u@\h:\l \W]\\$ "
  # fi
  # to your custom modification shell script in /etc/profile.d/ directory
fi

if ! shopt -q login_shell ; then # We're not a login shell
    # Need to redefine pathmunge, it get's undefined at the end of /etc/profile
    pathmunge () {
        case ":${PATH}:" in
            *:"$1":*)
                ;;
            *)
                if [ "$2" = "after" ] ; then
                    PATH=$PATH:$1
                else
                    PATH=$1:$PATH
                fi
        esac
    }
    # By default, we want umask to get set. This sets it for non-login shell.
    # Current threshold for system reserved uid/gids is 200
    # You could check uidgid reservation validity in
    # /usr/share/doc/setup-*/uidgid file
    if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
       umask 002
    else
       umask 022
    fi

    SHELL=/bin/bash
    # Only display echos from profile.d scripts if we are no login shell
    # and interactive - otherwise just process them to set envvars
    for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            if [ "$PS1" ]; then
                . "$i"
            else
                . "$i" >/dev/null
            fi
        fi
    done

    unset i
    unset -f pathmunge
fi
# vim:ts=4:sw=4

 

用户的bashprofile:

~/.bash_profile 

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

export PATH
[root@ckl1 bashtest]# echo $HOME
/root

 

全局profile:

"/etc/profile" 

# /etc/profile

# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

pathmunge () {
    case ":${PATH}:" in
        *:"$1":*)
            ;;
        *)
            if [ "$2" = "after" ] ; then
                PATH=$PATH:$1
            else
                PATH=$1:$PATH
            fi
    esac
}


if [ -x /usr/bin/id ]; then
    if [ -z "$EUID" ]; then
        # ksh workaround
        EUID=`/usr/bin/id -u`
        UID=`/usr/bin/id -ru`
    fi
    USER="`/usr/bin/id -un`"
    LOGNAME=$USER
    MAIL="/var/spool/mail/$USER"
fi

# Path manipulation
if [ "$EUID" = "0" ]; then
    pathmunge /usr/sbin
    pathmunge /usr/local/sbin
else
    pathmunge /usr/local/sbin after
    pathmunge /usr/sbin after
fi

HOSTNAME=`/usr/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
    export HISTCONTROL=ignoreboth
else
    export HISTCONTROL=ignoredups
fi

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL

# By default, we want umask to get set. This sets it for login shell
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
    umask 002
else
    umask 022
fi


for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then 
            . "$i"
        else
            . "$i" >/dev/null
        fi
    fi
done

unset i
unset -f pathmunge

#java environment
export JAVA_HOME=/usr/local/jdk1.8.0_161
export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
export PATH=$PATH:${JAVA_HOME}/bin

 

关于别名:

别名,典型的如ll,是ls -l 的别名,那么这个别名定义在哪呢,其实是在/etc/profile.d/colorls.sh 中,也就是我在上面几个文件中,标红的部分。

colorls.sh:

# color-ls initialization

# Skip all for noninteractive shells.
[ ! -t 0 ] && return

#when USER_LS_COLORS defined do not override user LS_COLORS, but use them.
if [ -z "$USER_LS_COLORS" ]; then

  alias ll='ls -l' 2>/dev/null
  alias l.='ls -d .*' 2>/dev/null

  INCLUDE=
  COLORS=

  for colors in "$HOME/.dir_colors.$TERM" "$HOME/.dircolors.$TERM" \
      "$HOME/.dir_colors" "$HOME/.dircolors"; do
    [ -e "$colors" ] && COLORS="$colors" && \
    INCLUDE="`/usr/bin/cat "$COLORS" | /usr/bin/grep '^INCLUDE' | /usr/bin/cut -d ' ' -f2-`" && \
    break
  done

  [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS.$TERM" ] && \
  COLORS="/etc/DIR_COLORS.$TERM"

  [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS.256color" ] && \
  [ "x`/usr/bin/tty -s && /usr/bin/tput colors 2>/dev/null`" = "x256" ] && \
  COLORS="/etc/DIR_COLORS.256color"

  [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS" ] && \
  COLORS="/etc/DIR_COLORS"

  # Existence of $COLORS already checked above.
  [ -n "$COLORS" ] || return

  if [ -e "$INCLUDE" ];
  then
    TMP="`/usr/bin/mktemp .colorlsXXX -q --tmpdir=/tmp`"
    [ -z "$TMP" ] && return

    /usr/bin/cat "$INCLUDE" >> $TMP
    /usr/bin/grep -v '^INCLUDE' "$COLORS" >> $TMP

    eval "`/usr/bin/dircolors --sh $TMP 2>/dev/null`"
    /usr/bin/rm -f $TMP
  else
    eval "`/usr/bin/dircolors --sh $COLORS 2>/dev/null`"
  fi

  [ -z "$LS_COLORS" ] && return
  /usr/bin/grep -qi "^COLOR.*none" $COLORS >/dev/null 2>/dev/null && return
fi

unset TMP COLORS INCLUDE

alias ll='ls -l --color=auto' 2>/dev/null
alias l.='ls -d .* --color=auto' 2>/dev/null
alias ls='ls --color=auto' 2>/dev/null
(END)
View Code

 

所以,什么情况下可以执行别名呢:

1:执行了/etc/profile

2:执行了~/.bashrc,~/.bashrc中引用了 /etc/bashrc(在该文件中,执行了ll别名所在的colorls.sh文件)

3:执行了~/.bash_profile,因为该文件中判断是否存在~/.bashrc,存在的话,会去执行~/.bashrc;根据上一步的结论,自然也就可以执行别名。

ok。那么,进一步,什么情况会执行上述的两种情况:

第一种情况(/etc/profile):

查阅了man bash后,发现:

1.交互的登录shell,或者--login选项的非交互shell。

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes

commands from the file /etc/profile, if that file exists. After reading that file, it  looks for ~/.bash_profile, ~/.bash_login, and ~/.profile,

in that order, and reads and executes commands from the first one that exists and is readable.

The --noprofile option may be used when the shell is started to inhibit this behavior.

 

不过在我的centos7中,~/.profile不存在。

 

第二种情况(~/.bashrc):

1.交互的,但不是登录的shell。

When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists.

This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.

第三种情况(~/.bash_profile):

同情况1。

 

Shell的几种类型:

ok。那么看了上面两种还是很蒙,那么我们再科普下什么是交互shell、非交互shell、登录shell和非登录shell。

我是参考了这里:https://blog.csdn.net/wisgood/article/details/52043522

我的理解:

登录shell:

ssh登录的,就是登录shell,登录shell要退出的话,是执行logout。比如我们用的putty、securtCRT。

非登录shell:

登录成功了之后,或者并没有进行远程登录,直接就在本机的(VMVARE的虚拟机中的shell都不能算,可采用下面的方法测试)ubuntu打开终端,这种,我理解的就是非登录shell。

我做了个小实验,我是secureCRT远程到该服务器的,在/home/upload/bashtest/a.sh中,我写了句logout:

[root@ckl1 bashtest]# less a.sh 
#/bin/bash

logout

执行该脚本:

[root@ckl1 bashtest]# ./a.sh 

结果:

./a.sh: line 3: logout: not login shell: use `exit'

 

 

区分登录与非登录shell的好办法:

https://unix.stackexchange.com/questions/38175/difference-between-login-shell-and-non-login-shell

1.通过echo $0,如果结果是-bash,那就是login shell。否则不是。

 

2.如果可以执行logout命令,那么就是login shell;否则不是。

 

交互shell:

就是我们不管是用SecurtCRT这样的工具进入远程服务器也好,或者本机打开终端也好,都可以执行各种命令

在执行这些命令时,shell是可以和我们互动的,比如要求我们输入东西,比如按Tab可以提示,等等。

 

 非交互Shell:

shell脚本执行,一般来说就是非交互的,我们写好了脚本,只要交给shell执行就好,期间不需要和我们交互。命令输入错了,会直接提示并退出。

 

以上两种,其实是不同维度,可以两两组合

  交互 非交互
登录 远程登录ssh,调用的文件包括:/etc/profile,~/.bash_profile,~/.bash_login,~/.profile 较少见,可能读/etc/profile , ~/.profile。也可能不读。依然请参考第一个答案:https://unix.stackexchange.com/questions/38175/difference-between-login-shell-and-non-login-shell
非登录 本机打开终端,调用文件包括:~/.bashrc 执行shell脚本,调用文件包括:BASH_ENV 指定的文件

 

 

 

 

 

 

 

非交互shell中,怎么才能使用别名:

参考:

https://stackoverflow.com/questions/1615877/why-aliases-in-a-non-interactive-bash-shell-do-not-work

 

方式1:

shopt -s expand_aliases

不过我的centos 7,未生效。

方式2:

 source their .bashrc at the end of their profile。

也就是在~/.bash_profile中新增一行:source ~/.bashrc

但是我这边依然没生效。

方式3:

直接脚本中增加:source ~/.bashrc

#/bin/bash
ls -l

echo "ll "
source ~/.bashrc

ll

 

ok。可以正常工作。

 

ssh执行远程命令时,怎么才能使用别名:

1.

首先修改远程主机的~/.bashrc,新增一行:

shopt -s expand_aliases
 再使用:

ssh -t @host ll

2.

ssh @host 'bash -ci ll'

 

参考:

https://stackoverflow.com/questions/1198378/ssh-command-execution-doesnt-consider-bashrc-bash-login-ssh-rc 

https://stackoverflow.com/questions/1615877/why-aliases-in-a-non-interactive-bash-shell-do-not-work

posted @ 2018-04-20 16:10  三国梦回  阅读(4730)  评论(0编辑  收藏  举报