shell下精确的定位一个命令

之前在这篇SIGTTIN? 里提出了问题,但没有交代背景,为什么用交互式shell执行”which mvn”命令,是为了更准确的获取用户当前环境里所用的mvn命令到底是哪个。若用户对mvn做过alias,优先使用alias过的指令,然后再选择$PATH路径下的命令;这个函数的完整内容如下:

function get_mvn_cmd() {
  if [[ "$OSTYPE" == *cygwin* ]];then
    ppid=$( ps -ef -p $$ | awk 'NR==2{print $3}' )
    user_shell=$( ps -p $ppid | awk 'NR==2{print $8}' )
    #has some trouble with cygwin, while Ctrl-c cannot terminal
    set -m
  else
    ppid=$( ps -oppid= $$ )
    user_shell=$( ps -ocomm= -p $ppid )
  fi

  # while as login shell, it's -bash not bash
  if [[ "$user_shell" == "-"* ]];then
    user_shell=${user_shell:1}
  fi

  mvn=$( $user_shell -ic "alias mvn" 2>/dev/null | cut -d'=' -f2 | sed "s/'//g" )

  if [ -z "$mvn" ];then
    $user_shell -ic "which mvn" >/dev/null
    if [ $? -eq 0 ];then
      mvn=$( $user_shell -ic "which mvn" | head -1 )
    fi
  fi

  if [ -z "$mvn" ]; then
    echo "mvn command not found" >&2
    kill -s TERM $TOP_PID
  else
    echo $mvn
  fi
}

函数里先获取用户所使用的shell(即当前脚本的父进程),然后以交互式执行alias mvn看看是否又被用户别名过,没有的话再使用which mvn获取mvn命令。

为什么写的那么啰嗦是想兼容好几种用户环境,如果是linux或者使用的gnu-which,可以利用gnu-which的一些参数一次性按优先级依次从”alias, functions, commands”里查找命令

$ (alias; declare -f) | gwhich --read-alias --read-functions mvn

上面利用gnu-which的--read-alias--read-functions参数优先从前边aliasdeclare -f输出的结果里查找,最后再从$PATH里查找。实际上centos7的bash下which命令就被alias过了:

alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'    

Leave a Reply

Your email address will not be published. Required fields are marked *