无法运行脚本(可执行,哈希标记与 shell 匹配)

无法运行脚本(可执行,哈希标记与 shell 匹配)

为了方便阅读,我把问题分成了几个部分,虽然听起来可能有点生硬

问题:无法从我认为是 bash shell 的地方执行 bash 脚本。

背景:我正尝试开始使用 LibGDX,他们希望我在 Eclipse 中安装 Android SDK。因此,我得到了这个脚本,它应该安装我下载的所有内容。

规格:HP Compaq dc7900 小型机 内存:3.8 GiB 显卡:AMD RV620 上的 Gallium 0.4(DRM 2.46.0 / 4.8.0-52-generic、LLVM 3.8.0)

处理器:Intel® Core™2 Duo CPU E8400 @ 3.00GHz × 2

操作系统:Ubuntu 16.04 64位

Android SDK 修订版 26.0.2(2017 年 4 月) https://developer.android.com/studio/releases/sdk-tools.html

问题历史

将权限更改为所有人可执行的读/写权限

权限设置如图所示

根据 head 命令的输出,哈希爆炸线

$sudo head -1 android
#!/bin/bash

检查 shell 的输出

$ echo $0
/bin/bash

在与目标脚本相同的文件夹中打开终端,并尝试以下命令,输出直接在其下方。

$ sh android.sh
sh: 0: Can't open android.sh

$ sudo sh android.sh
[sudo] password for joel: [TYPES PASSWORD]
sh: 0: Can't open android.sh

$sh android 
android: 24: android: Syntax error: redirection unexpected

$sudo sh android
android: 24: android: Syntax error: redirection unexpected

我也尝试过在 ~/ 和 ./ 前面加上前缀,但是没有效果;唯一的规律是,如果包含文件扩展名,则会出现“无法打开”的情况,而如果省略,则会出现“重定向意外”的情况

有趣的是,我尝试打开一个不存在的文件 eirugheur.sh,但出现了同样的错误。

$sudo sh eirugheur.sh
sh: 0: Can't open eirugheur.sh

所以我无法知道“无法打开”是否意味着文件丢失,或者我是否错误地输入了命令。

感谢您的阅读,欢迎提出任何建议或解决方法。

编辑: ls -l 的输出

joel@joel-HP-Compaq-dc7900-Small-Form-Factor:~/Downloads/tools$ ls -l
total 1680
-rwxrwxrwx 1 joel joel   4741 May 31 15:01 android
drwxrwxr-x 2 joel joel   4096 Mar 29 00:46 bin
-rwxrw-rw- 1 joel joel 643536 Mar 29 00:46 emulator
-rwxrw-rw- 1 joel joel 394336 Mar 29 00:46 emulator-check
drwxrwxr-x 6 joel joel   4096 Mar 29 00:46 lib
-rwxrw-rw- 1 joel joel  12191 Mar 29 00:46 mksdcard
-rwxrw-rw- 1 joel joel   1257 Mar 29 00:46 monitor
-rw-rw-rw- 1 joel joel 629709 Mar 29 00:46 NOTICE.txt
drwxrwxr-x 7 joel joel   4096 Mar 29 00:46 proguard
-rw-rw-rw- 1 joel joel    139 Mar 29 00:46 source.properties
drwxrwxr-x 2 joel joel   4096 Mar 29 00:46 support
joel@joel-HP-Compaq-dc7900-Small-Form-Factor:~/Downloads/tools$

目前正在阅读steeldriver的链接

编辑:尝试过steeldriver./android

输出:

The "android" command is deprecated.
For manual SDK, AVD, and project management, please use Android Studio.
For command-line tools, use tools/bin/sdkmanager and tools/bin/avdmanager
*************************************************************************
Invalid or unsupported command ""

Supported commands are:
android list target
android list avd
android list device
android create avd
android move avd
android delete avd
android list sdk
android update sdk

这是脚本,steeldriver 的解决方案有效,因为该错误消息来自脚本内部。感谢您的帮助,我想我会着手解决下一个问题 >.>

#!/bin/bash

# Attempt to set app_home
# Resolve links: $0 may be a link
prg="$0"
# Need this for relative symlinks.
while [ -h "$prg" ] ; do
  ls=`ls -ld "$prg"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    prg="$link"
  else
    prg=`dirname "$prg"`"/$link"
  fi
done
saved="`pwd`"
cd "`dirname \"$prg\"`" >/dev/null
app_home="`pwd -P`"
cd "$saved" >/dev/null

ANDROID_WRAPPER_BIN_DIR=${ANDROID_WRAPPER_BIN_DIR:-$app_home/bin}
ANDROID_WRAPPER_SDK_TIMEOUT=${ANDROID_WRAPPER_SDK_TIMEOUT:-20}

cat <<< \
"*************************************************************************
The \"android\" command is deprecated.
For manual SDK, AVD, and project management, please use Android Studio.
For command-line tools, use tools/bin/sdkmanager and tools/bin/avdmanager
*************************************************************************"

function usage {
  echo "Invalid or unsupported command \"$@\""
  echo
  echo "Supported commands are:"
  echo "android list target"
  echo "android list avd"
  echo "android list device"
  echo "android create avd"
  echo "android move avd"
  echo "android delete avd"
  echo "android list sdk"
  echo "android update sdk"
  exit 2
}

function matches {
  verbs=$1
  objects=$2
  verb=""
  object=""
  shift 2

  for arg in "$@"; do
    if [[ $arg =~ ^- ]]; then
      continue
    fi
    if [[ -z $verb && $verbs =~ ( |^)$arg( |$) ]]; then
      verb=$arg
      continue
    fi
    if [[ -n $verb && $objects =~ ( |^)$arg( |$) ]]; then
      object=$arg
      break
    fi
    break
  done
  return $([[ -n $verb && -n $object ]])
}

function echo_and_exec {
  echo "Running $@"
  echo
  exec $@
}

function parse_filter {
  local IFS=,
  for filter in $1; do
    if [[ $filter == tool || $filter == platform-tool || $filter == doc ]]; then
      command+=( "$args ${filter}s" )
    elif [[ $filter == tools || $filter == platform-tools ]]; then
      command+=( "$args ${filter}" )
    elif [[ $filter =~ ^lldb ]]; then
      command+=( "$args ${filter/-/;}" )
    elif [[ $filter =~ ^build-tools ]]; then
      command+=( "$args ${filter/build-tools-/build-tools;}" )
    elif [[ $filter == ndk ]]; then
      command+=( "$args ndk-bundle" )
    elif [[ $filter =~ ^android- ]]; then
      command+=( "$args platforms;$filter" )
    else
      echo Filter $filter not supported
      exit 2
    fi
  done
}

function confirm_try_sdk {
  for arg in "$@"; do
    if [[ $arg == --use-sdk-wrapper ]]; then
      return 0
    fi
  done
  if [[ -n $USE_SDK_WRAPPER ]]; then
    return 0
  fi
  read -t $ANDROID_WRAPPER_SDK_TIMEOUT -p "\"android\" SDK commands can be translated to sdkmanager commands on a best-effort basis.
Continue? (This prompt can be suppressed with the --use-sdk-wrapper command-line argument
or by setting the USE_SDK_WRAPPER environment variable) [y/N]: " trysdkresponse
  if (( $? > 128 )); then
    echo "Timed out waiting for input."
    echo "To suppress this prompt, run with --use-sdk-wrapper or set USE_SDK_WRAPPER."
    exit 1
  fi
  if [[ ${trysdkresponse,,} == y ]]; then
    return 0
  fi
  echo Aborted
  exit 1
}

avd_verbs="list create move delete"
avd_objects="avd target device"

if matches "$avd_verbs" "$avd_objects" "$@"; then
  echo_and_exec "$ANDROID_WRAPPER_BIN_DIR/avdmanager" "$@"
fi

sdk_verbs="list update"
sdk_objects="sdk"

if matches "$sdk_verbs" "$sdk_objects" "$@"; then
  confirm_try_sdk $@
  if [[ $verb == list ]]; then
    echo_and_exec "$ANDROID_WRAPPER_BIN_DIR/sdkmanager" --list --verbose
  fi
  if [[ $verb == update ]]; then
    command=( "$ANDROID_WRAPPER_BIN_DIR/sdkmanager" )
    prev=""
    update_all=1
    for arg in "$@"; do
      if [[ $arg == --use-sdk-wrapper || $arg == $verb || $arg == $object ]]; then
        continue
      elif [[ $arg == -n ]]; then
        echo "update sdk -n is not supported"
        exit 2
      elif [[ $arg == -s || $arg == --no-https ]]; then
        command+=("--no_https")
      elif [[ $arg == -a || $arg == --all ]]; then
        command+=("--include_obsolete")
      elif [[ $arg == -p || $arg == --obsolete || $arg == -u || $arg == --no-ui || $arg == --proxy-host ||
        $arg == --proxy-port || $arg == -t || $arg == --filter ]]; then
        :
      elif [[ $prev == --proxy-host ]]; then
        command+=("--proxy=http" "--proxy_host=$arg")
      elif [[ $prev == --proxy-port ]]; then
        command+=("--proxy_port=$arg")
      elif [[ $prev == -t || $prev == --filter ]]; then
        update_all=
        parse_filter $arg
      else
        echo Unrecognized argument $arg
        exit 2
      fi

      prev=$arg
    done
    if [[ -n $update_all ]]; then
      command+=("--update")
    fi
    echo_and_exec ${command[@]}
  fi
fi

usage $@

答案1

正如您的图片所示,该文件的名称很简单android- 因此任何使用名称运行它的尝试android.sh都不会奏效。

你尝试运行它sh也注定会失败,因为sh不是bash。无论您从哪条#!线路或哪个交互式 shell$0运行它,这都适用。(特别是,dash不支持进程替换之类的功能 - 这可能是导致Syntax error: redirection unexpected消息的原因。)

从终端执行它的最简单方法是首先确保执行位已设置:

chmod +x android

然后使用运行它

./android

./必要告诉 shell在哪里查找文件(即当前目录)。您可以bash android明确使用,但更好的做法是让 hashbang 确定使用哪个解释器。

相关内容