"builtin: not found" 当我通过 PHP passthru() 获取脚本时

"builtin: not found" when I source a script via PHP passthru()

我已经通过 https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer

安装了 RVM

我在 Ubuntu 并且我使用 Bash。

安装后,我需要能够基于 installation instructions 获取源 ~/.rvm/scripts/rvm。 我需要通过 CLI (test.sh) 执行一个脚本来做到这一点,该脚本又调用一个 PHP 脚本 (test.php),该脚本通过 shell 命令进行采购。 一旦我这样做,我就会收到关于 builtin:

的错误
$ ./test.sh
sh: 10: /home/housni/.rvm/scripts/rvm: builtin: not found

这是 test.sh 运行 在 Bash 上调用 test.php

#!/bin/bash
./test.php

这是test.php

#!/usr/bin/php -q
<?php
    passthru('. ~/.rvm/scripts/rvm');
?>

当我直接在终端 (bash) 中键入 source ~/.rvm/scripts/rvm 并执行它时,我没有看到任何错误。

在我看来,RVM 脚本试图执行 dash 而不是 bash,但这并不完全有意义,因为 RVM 脚本以 #!/usr/bin/env bash 开头。

知道我在 PHP 脚本中做错了什么吗?

以下是~/.rvm/scripts/rvm的内容:

#!/usr/bin/env bash

# rvm : Ruby enVironment Manager
# https://rvm.io
# https://github.com/wayneeseguin/rvm

# partial duplication marker dkjnkjvnckbjncvbkjnvkj
# prevent from loading in sh shells
if
  builtin test -n "${BASH_VERSION:-}" -o -n "${ZSH_VERSION:-}" -o -n "${KSH_VERSION:-}"
then
  case "`uname`" in
    (CYGWIN*) __shell_name="`\command \ps -p $$ | \command \awk 'END {print $NF}'` 2>/dev/null" ;;
    (SunOS)   __shell_name="`\command \ps -p $$ -o comm=`" ;;
    (*)       __shell_name="`\command \ps -p $$ -o ucomm=`" ;;
  esac
  case "$__shell_name" in
    (""|dash|sh|ksh|*/dash|*/sh|*/ksh) return 0 ;; # silently stop in sh shells
  esac
  unset __shell_name
else
  return 0
fi

# also duplicated in scripts/base
__rvm_has_opt()
{
  if # pre-gnu
   [[ -n "${ZSH_VERSION}"  ]]
  then
    setopt | GREP_OPTIONS="" \command \grep "^$" >/dev/null 2>&1 || return $?
  elif # mksh
    [[ -n "${KSH_VERSION}"  ]]
  then
    set +o | GREP_OPTIONS="" \command \grep "-o $" >/dev/null 2>&1 || return $?
  elif # bash
    [[ -n "${BASH_VERSION}" ]]
  then
    [[ ":$SHELLOPTS:" == *"::"* ]] || return $?
  else # what is this?!
    return 1
  fi
}

# Do not allow sourcing RVM in `sh` - it's not supported
# return 0 to exit from sourcing this script without breaking sh
if __rvm_has_opt "posix"
then return 0
fi

# TODO: Alter the variable names to make sense
\export HOME rvm_prefix rvm_user_install_flag rvm_path
HOME="${HOME%%+(\/)}" # Remove trailing slashes if they exist on HOME

[[ -n "${rvm_stored_umask:-}" ]] || export rvm_stored_umask=$(umask)
if (( ${rvm_ignore_rvmrc:=0} == 0 ))
then
  rvm_rvmrc_files=("/etc/rvmrc" "$HOME/.rvmrc")
  if [[ -n "${rvm_prefix:-}" ]] && ! [[ "$HOME/.rvmrc" -ef "${rvm_prefix}/.rvmrc" ]]
  then rvm_rvmrc_files+=( "${rvm_prefix}/.rvmrc" )
  fi

  for rvmrc in "${rvm_rvmrc_files[@]}"
  do
    if [[ -f "$rvmrc" ]]
    then
      # pre-gnu
      if GREP_OPTIONS="" \command \grep '^\s*rvm .*$' "$rvmrc" >/dev/null 2>&1
      then
        printf "%b" "
Error:
        $rvmrc is for rvm settings only.
        rvm CLI may NOT be called from within $rvmrc.
        Skipping the loading of $rvmrc"
        return 1
      else
        source "$rvmrc"
      fi
    fi
  done
  unset rvm_rvmrc_files
fi

# duplication marker jdgkjnfnkjdngjkfnd4fd
# detect rvm_path if not set
if
  [[ -z "${rvm_path:-}" ]]
then
  if
    [[ -n "${BASH_SOURCE:-$_}" && -f "${BASH_SOURCE:-$_}" ]]
  then
    rvm_path="${BASH_SOURCE:-$_}"
    rvm_path="$( \command \cd "${rvm_path%/scripts/rvm}">/dev/null; pwd )"
    rvm_prefix=$( dirname $rvm_path )
  elif
    [[ "${UID:-}" == "0" || "${USER:-}" == "root" ]]
  then
    if
      (( ${rvm_user_install_flag:-0} == 0 ))
    then
      rvm_prefix="/usr/local"
      rvm_path="${rvm_prefix}/rvm"
    else
      rvm_prefix="$HOME"
      rvm_path="${rvm_prefix}/.rvm"
    fi
  else
    if
      [[ -d "$HOME/.rvm" && -s "$HOME/.rvm/scripts/rvm" ]]
    then
      rvm_prefix="$HOME"
      rvm_path="${rvm_prefix}/.rvm"
    else
      rvm_prefix="/usr/local"
      rvm_path="${rvm_prefix}/rvm"
    fi
  fi
else
  # remove trailing slashes, btw. %%/ <- does not work as expected
  rvm_path="${rvm_path%%+(\/)}"
fi

# guess rvm_prefix if not set
if [[ -z "${rvm_prefix}" ]]
then
  rvm_prefix=$( dirname $rvm_path )
fi

# duplication marker kkdfkgnjfndgjkndfjkgnkfjdgn
[[ -n "${rvm_user_install_flag:-}" ]] ||
case "$rvm_path" in
  (/usr/local/rvm)         rvm_user_install_flag=0 ;;
  ($HOME/*|/${USER// /_}*) rvm_user_install_flag=1 ;;
  (*)                      rvm_user_install_flag=0 ;;
esac

export rvm_loaded_flag
if [[ -n "${BASH_VERSION:-}" || -n "${ZSH_VERSION:-}" ]] &&
  \typeset -f rvm >/dev/null 2>&1
then
  rvm_loaded_flag=1
else
  rvm_loaded_flag=0
fi

if
  (( ${rvm_loaded_flag:=0} == 0 )) || (( ${rvm_reload_flag:=0} == 1 ))
then
  if
    [[ -n "${rvm_path}" && -d "$rvm_path" ]]
  then
    true ${rvm_scripts_path:="$rvm_path/scripts"}

    if
      [[ ! -f "$rvm_scripts_path/base" ]]
    then
      printf "%b" "WARNING:
      Could not source '$rvm_scripts_path/base' as file does not exist.
      RVM will likely not work as expected.\n"
    elif
      ! source "$rvm_scripts_path/base"
    then
      printf "%b" "WARNING:
      Errors sourcing '$rvm_scripts_path/base'.
      RVM will likely not work as expected.\n"
    else
      __rvm_ensure_is_a_function
      __rvm_setup

      export rvm_version
      rvm_version="$(\command \cat "$rvm_path/VERSION") ($(\command \cat "$rvm_path/RELEASE" 2>/dev/null))"

      alias rvm-restart="rvm_reload_flag=1 source '${rvm_scripts_path:-${rvm_path}/scripts}/rvm'"

      # Try to load RVM ruby if none loaded yet
      __path_to_ruby="$( builtin command -v ruby 2>/dev/null || true )"
      if
        [[ -z "${__path_to_ruby}" ]] ||
        [[ "${__path_to_ruby}" != "${rvm_path}"* ]] ||
        [[ "${__path_to_ruby}" == "${rvm_path}/bin/ruby" ]]
      then
        if
          [[ -n "${rvm_environments_path:-}" &&
            -s "${rvm_environments_path}/default"
          ]]
        then
          source "${rvm_environments_path}/default"
        elif
          [[ "${rvm_environments_path:-}" != "${rvm_path}/environments" &&
            -s "${rvm_path}/environments/default"
          ]]
        then
          source "${rvm_path}/environments/default"
        fi
        if
          [[ ${rvm_project_rvmrc:-1} -gt 0 ]] &&
          ! __function_on_stack __rvm_project_rvmrc
        then
          # Reload the rvmrc, use promptless ensuring shell processes does not
          # prompt if .rvmrc trust value is not stored, revert to default on fail
          if
            rvm_current_rvmrc=""
            rvm_project_rvmrc_default=2 rvm_promptless=1 __rvm_project_rvmrc
          then
            rvm_hook=after_cd
            source "${rvm_scripts_path:-${rvm_path}/scripts}/hook"
          fi
        fi
      elif
        [[ "${__path_to_ruby}" == "${rvm_path}"* ]] &&
        [[ -z "${GEM_HOME:-}" || -z "${GEM_PATH:-}" ]]
      then
        echo "
Warning: PATH set to RVM ruby but GEM_HOME and/or GEM_PATH not set, see:
    https://github.com/wayneeseguin/rvm/issues/3212
" >&2
        if
          [[ -n "${SUDO_USER:-}" ]]
        then
          echo "Hint: To fix PATH errors try using 'rvmsudo' instead of 'sudo', see:
    
" >&2
        fi
      fi
      unset __path_to_ruby

      # Makes sure rvm_bin_path is in PATH atleast once.
      [[ ":${PATH}:" == *":${rvm_bin_path}:"* ]] || PATH="$PATH:${rvm_bin_path}"

      if
        (( ${rvm_reload_flag:=0} == 1 ))
      then
        [[ "${rvm_auto_reload_flag:-0}" == 2 ]] || printf "%b" 'RVM reloaded!\n'
        unset __rvm_project_rvmrc_lock
      fi

      rvm_loaded_flag=1
      __rvm_teardown

      # Opt-in for custom prompt through by setting:
      #     rvm_ps1=1
      # in either /etc/rvmrc or $HOME/.rvmrc
      if
        [[ ${rvm_ps1:-0} -eq 1 ]]
      then
        # Source RVM ps1 functions for a great prompt.
        if
          [[ -s "$rvm_path/contrib/ps1_functions" ]]
        then
          source "$rvm_path/contrib/ps1_functions"
        elif
          [[ -s "/usr/local/rvm/contrib/ps1_functions" ]]
        then
          source "/usr/local/rvm/contrib/ps1_functions"
        fi

        if command -v ps1_set >/dev/null 2>&1
        then ps1_set
        fi
      fi

    fi
  else
    printf "%b" "\n$rvm_path ($rvm_path) does not exist."
  fi
  unset rvm_prefix_needs_trailing_slash rvm_gems_cache_path rvm_gems_path rvm_project_rvmrc_default rvm_gemset_separator rvm_reload_flag
fi

运行 作为 . ~/.rvm/scripts/rvm 的脚本不使用其 shebang 行。它将脚本源到当前 shell。 passthru 的当前 shell 似乎是 /bin/sh(大多数情况下默认使用 /bin/sh 是合理的)。

如果您希望使用脚本的 shebang,则需要停止 sourcing ./source 命令。