代码之家  ›  专栏  ›  技术社区  ›  kittygirl

`运行bash脚本“useradd”和“groupadd”[重复]时,'不是有效的组名'

  •  -1
  • kittygirl  · 技术社区  · 7 年前

    我正在Mac上制作一个NW.js应用程序,并希望通过双击图标以开发模式运行该应用程序。第一步,我要让shell脚本正常工作。

    在Windows上使用VSCode(我想争取时间),我创建了一个 run-nw 文件,包含以下内容:

    #!/bin/bash
    
    cd "src"
    npm install
    
    cd ..
    ./tools/nwjs-sdk-v0.17.3-osx-x64/nwjs.app/Contents/MacOS/nwjs "src" &
    

    但我得到的结果是:

    $ sh ./run-nw
    
    : command not found  
    : No such file or directory  
    : command not found  
    : No such file or directory  
    
    Usage: npm <command>
    
    where <command> is one of:  (snip commands list)
    
    (snip npm help)
    
    npm@3.10.3 /usr/local/lib/node_modules/npm  
    : command not found  
    : No such file or directory  
    : command not found
    

    我真的不明白:

    • 它似乎以空行作为命令。在我的编辑器(VSCode)中,我尝试替换 \r\n 具有 \n \r 制造问题),但它什么也没改变。
    • dirname 或者它不知道 cd 命令?
    • install npm
    • 真正让我感到奇怪的是,它仍然在运行这个应用程序(如果我做了一个测试的话) npm install 手动)。。。

    由于无法使其正常工作,并且怀疑文件本身有什么奇怪的地方,我直接在Mac上创建了一个新的文件,这次使用的是vim。我输入了完全相同的指令,然后。。。现在它的工作没有任何问题。
    两个文件的差异显示完全没有差异。

    有什么区别?什么能使第一个脚本不起作用?我怎么知道?

    ~/.gitconfig 在我的Windows机器上,我 autocrlf=true ,所以每次我在Windows下修改bash文件时,它都会将行尾重新设置为 \\r\n .

    0 回复  |  直到 9 年前
        1
  •  3
  •   Gordon Davisson    5 年前

    对。Bash脚本 是 无论是在脚本本身还是它处理的数据中,都对行尾敏感。它们应该有Unix风格的行尾,即每行以换行符(十进制10,ASCII中的十六进制0A)结束。

    对于Windows或DOS样式的行结束符,每行都以回车符和换行符结束。您可以在的输出中看到这个不可见的字符 cat -v yourfile

    $ cat -v yourfile
    #!/bin/bash^M
    ^M
    cd "src"^M
    npm install^M
    ^M
    cd ..^M
    ./tools/nwjs-sdk-v0.17.3-osx-x64/nwjs.app/Contents/MacOS/nwjs "src" &^M
    

    在这种情况下,回车( ^M 插入符号或 \r 在C语言中,转义符号)不被视为空白。Bash将shebang后面的第一行(由单个回车符组成)解释为要运行的命令/程序的名称。

    • ^米 ,它打印出来了 : command not found
    • "src"^M (或 src^M ),它打印出来了 : No such file or directory
    • install^M 而不是 install 作为一个论据 npm npm公司

    DOS/Windows输入数据中的行尾

    如上所述,如果您有一个带有回车符的输入文件:

    hello^M
    world^M
    

    然后,在编辑器和将其写入屏幕时,它看起来完全正常,但工具可能会产生奇怪的结果。例如, grep 将无法找到明显存在的行:

    $ grep 'hello$' file.txt || grep -x "hello" file.txt
    (no match because the line actually ends in ^M)
    

    追加的文本将覆盖行,因为回车会将光标移到行的开头:

    $ sed -e 's/$/!/' file.txt
    !ello
    !orld
    

    $ a="hello"; read b < file.txt
    $ if [[ "$a" = "$b" ]]
      then echo "Variables are equal."
      else echo "Sorry, $a is not equal to $b"
      fi
    
    Sorry, hello is not equal to hello
    

    解决方案是将文件转换为使用Unix样式的行尾。有许多方法可以实现这一点:

    1. dos2unix 课程:

      dos2unix filename
      
    2. 能干的 文本编辑器(Sublime,Notepad++,而不是Notepad)并将其配置为使用Unix行结尾保存文件(例如,使用Vim),在(重新)保存之前运行以下命令:

      :set fileformat=unix
      
    3. 如果你有一个版本的 sed 支持 -i --in-place 选项,例如GNU 塞德

      sed -i 's/\r$//' filename
      

      与其他版本的 塞德

      sed 's/\r$//' filename > filename.unix
      
    4. 同样地 tr 翻译过滤器可用于从输入中删除不需要的字符:

      tr -d '\r' <filename >filename.unix
      

    赛文·巴什

    对于Cygwin的Bash端口,有一个自定义 igncr 选项,可以设置为忽略行尾中的回车(可能是因为许多用户使用本机Windows程序编辑文本文件)。 这可以为 运行抽壳 set -o igncr .

    设置此选项仅适用于 现在的 采购 SHELLOPTS (所有大写字母)包括 . Bash使用此环境变量在启动时(在读取任何启动文件之前)设置shell选项。

    实用工具

    file 实用程序对于快速查看文本文件中使用的行尾非常有用。下面是它为每种文件类型打印的内容:

    • Bourne-Again shell script, ASCII text executable
    • Mac行结尾: Bourne-Again shell script, ASCII text executable, with CR line terminators
    • DOS行尾: Bourne-Again shell script, ASCII text executable, with CRLF line terminators

    GNU版本的 cat -v, --show-nonprinting 显示非打印字符的选项。

    这个 dos2unix系统

    有用的链接

    excellent article 涵盖了许多不同的方式来标记一行文字的结尾,这种编码的历史,以及新行是如何在不同的操作系统,编程语言和互联网协议(如FTP)处理。

    具有经典Mac OS行尾的文件

    Classic Mac OS (在OS X之前),每行都以回车结束(十进制13,ASCII中的十六进制0D)。如果脚本文件以这样的行结尾保存,Bash将只看到一行长的行,如下所示:

    #!/bin/bash^M^Mcd "src"^Mnpm install^M^Mcd ..^M./tools/nwjs-sdk-v0.17.3-osx-x64/nwjs.app/Contents/MacOS/nwjs "src" &^M
    

    因为这条长长的线是从一只章鱼开始的( # ),Bash将行(和整个文件)视为单个注释。

    注:2001年,苹果推出了基于BSD衍生的MacOSX NeXTSTEP 操作系统。因此,osx也使用Unix风格的LF-only行尾,从那时起,以CR结尾的文本文件变得极为罕见。不过,我认为有必要展示Bash如何尝试解释这些文件。

        2
  •  2
  •   Dimek Kengele dougparnoff    6 年前

    关于JetBrains产品(PyCharm、PHPStorm、IDEA等),您需要 点击 在 CRLF / LF 到 在两种类型的行分隔符之间( \r\n \n ).

    enter image description here enter image description here

        3
  •  1
  •   Ido Ran    6 年前

    如果问题是你的文件 ^M

    for f in *$'\r'; do
        mv "$f" "${f%$'\r'}"
    done
    

    您应该首先修复导致这些文件名称损坏的原因(可能是创建这些文件的脚本) dos2unix 但有时这是不可行的。

    这个 $'\r' 语法是特定于Bash的;如果你有一个不同的shell,也许你需要使用其他的符号。也许你也看到了 Difference between sh and bash

        4
  •  0
  •   Rafael Parungao    6 年前

    如果你用的是 read 可以 在DOS/Windows格式中,您可以利用 将从行首和行尾修剪空白。如果您告诉它回车符是空白(通过将它们添加到 IFS 变量),它将从线的末端修剪它们。

    在bash(或zsh或ksh)中,这意味着您将替换以下标准习惯用法:

    IFS= read -r somevar    # This will not trim CR
    

    有了这个:

    IFS=$'\r' read -r somevar    # This *will* trim CR
    

    (注:以下为 -r 选项与此无关,它通常是一个好主意,以避免损坏反斜杠。)

    如果你不使用 IFS=

    read -r field1 field2 ...    # This will not trim CR
    

    有了这个:

    IFS=$' \t\n\r' read -r field1 field2 ...    # This *will* trim CR
    

    $'...' 引用模式(例如,dash,某些Linux发行版上的默认/bin/sh),甚至是脚本 可以 如果使用这样的shell运行,那么您需要更复杂一些:

    cr="$(printf '\r')"
    IFS="$cr" read -r somevar    # Read trimming *only* CR
    IFS="$IFS$cr" read -r field1 field2 ...    # Read trimming CR and whitespace, and splitting fields
    

    如果 ,应尽快恢复正常,避免出现奇怪的副作用;但在所有这些情况下,它是 阅读 命令,所以它只影响一个命令,不必在之后重置。

        5
  •  0
  •   Natan Yellin    5 年前

    摆脱不需要的CR('\r')字符的另一种方法是运行 tr

    $ tr -d '\r' < dosScript.py > nixScript.py
    
        6
  •  0
  •   Jamie Smith    5 年前

    我正试图从Windows启动docker容器,结果是:

    Bash script and /bin/bash^M: bad interpreter: No such file or directory
    

    1. git config --global core.autocrlf input
    2. 删除本地存储库
    3. 再克隆一次。

    https://forums.docker.com/t/error-while-running-docker-code-in-powershell/34059/6

    在那之前,我试过这个,但没用:

    1. dos2unix scriptname.sh
    2. sed -i -e 's/\r$//' scriptname.sh
    3. sed -i -e 's/^M$//' scriptname.sh
    推荐文章