• 你可能不知道的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 "33]0;%s@%s:%s07" "${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 "33k%s@%s:%s33\" "${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

  • 相关阅读:
    高并发系统设计(二十):分布式架构如何跟踪排查慢请求问题?
    Git将多个commit合并成一个commit
    高并发系统设计(十九)【注册中心】:微服务架构结合RPC框架如何做到分布式系统寻址?
    高并发系统设计(十八):【RPC框架】10万QPS下如何实现毫秒级的服务调用?
    AfxSocketInit()
    TEXTMETRIC 结构详解
    OnInitialUpdate函数
    SetForegroundWindow
    GetSafeHwnd()函数
    MFC之CCommandLineInfo
  • 原文地址:https://www.cnblogs.com/grey-wolf/p/8891423.html
Copyright © 2020-2023  润新知