我对 Linux 还很陌生,在 CentOS 中一个非常简单的 Bash 脚本上遇到了问题。
#! /bin/bash
# script to restore the cognos rds from snapshot
export AWS_RDS_HOME=/opt/aws/apitools/rds
export PATH=$PATH:$AWS_RDS_HOME/bin
export AWS_CREDENTIAL_FILE=$AWS_RDS_HOME/credential-file-path.template
echo $AWS_RDS_HOME
echo $PATH
echo $AWS_CREDENTIAL_FILE
rds-delete-db-instance mydb --final-db-snapshot-identifier mydb-daily-$(date +%Y)-$(date +%m)-$(date +%d) --force -region eu-west-1
我添加了 echo 语句,以便能够看到发生了什么。当我运行
sh myscript.sh
是:
/opt/aws/apitools/rds
/bin/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin:/opt/aws/apitools/rds
/credential-file-path.template
rds-delete-db-instance: command not found
因此,当我引用在同一脚本中设置的其他环境变量时,导出命令似乎不起作用。
我哪里做错了?
谢谢
更新:我尝试了下面的建议,但仍然没有成功。运行 bash -x 很有趣。每当我尝试连接时,下面的“\r”是否可能位于此后面?例如
#! /bin/bash
# test script
export AWS_RDS_HOME=/opt/aws/apitools/rds
export PATH=$PATH:$AWS_RDS_HOME/bin
export AWS_CREDENTIAL_FILE=$AWS_RDS_HOME/credential-file-path.template
echo $AWS_RDS_HOME
echo $PATH
echo $AWS_CREDENTIAL_FILE
结果是:
+ export $'AWS_RDS_HOME=/opt/aws/apitools/rds\r'
+ AWS_RDS_HOME=$'/opt/aws/apitools/rds\r'
+ export $'PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin:/opt/aws/apitools/rds\r/bin\r'
+ PATH=$'/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin:/opt/aws/apitools/rds\r/bin\r'
+ export $'AWS_CREDENTIAL_FILE=/opt/aws/apitools/rds\r/credential-file-path.template\r'
+ AWS_CREDENTIAL_FILE=$'/opt/aws/apitools/rds\r/credential-file-path.template\r'
+ echo $'/opt/aws/apitools/rds\r\r'
/opt/aws/apitools/rds
+ echo $'/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin:/opt/aws/apitools/rds\r/bin\r\r'
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home//binuser/bin:/opt/aws/apitools/rds
+ echo $'/opt/aws/apitools/rds\r/credential-file-path.template\r'
/credential-file-path.template
我在 EC2 上使用默认的 Amazon Linux AMI,所以我的设置应该不会有什么问题
答案1
您通过运行“sh myscript.sh”来执行脚本。如果您使用“sh”调用 bash,bash 将尝试“尽可能地模仿 sh 历史版本的启动行为,同时符合 POSIX 标准”(根据 bash 手册页中的调用部分)。
历史悠久的 Bourne shell 无法识别“export VARIABLE=value”。Bourne shell 中导出变量的典型方式是“VARIABLE=value ; export VARIABLE”,即值的设置和导出是单独的命令。将它们全部作为一条命令执行是一种 bash 主义。
因此,您可以尝试以“bash myscript.sh”的形式调用脚本,这应该可以工作(对我来说是可行的,尽管不可否认,它也适用于“sh myscript.sh”调用;我的 shell 设置可能有些奇怪,或者您的 shell 设置有些奇怪)。您还可以使用“chmod +x myscript.sh”使文件可执行,然后直接使用“./myscript.sh”运行它,因为根据第一行中的“#!”,它应该调用 bash。
答案2
看来您的脚本在每一行末尾都有错误的回车符。如果脚本在其生命周期的某个时刻在 Windows 系统上被编辑过,则可能会发生这种情况。您可以尝试使用以下命令进行修复:
perl -pi -e 's/\r//' myscript.sh
由于错误的回车符,它没有rds
像您预期的那样引用目录,而是后面rds
跟着一个回车符。您大概没有同名的目录,并且假设rds-delete-db-instance
位于rds
目录内,这就解释了为什么您会得到command not found
。
您的脚本还存在一些其他问题,我已尝试在此处修复:
#!/bin/bash
# script to restore the cognos rds from snapshot
export AWS_RDS_HOME=/opt/aws/apitools/rds
export PATH="$PATH:$AWS_RDS_HOME/bin"
export AWS_CREDENTIAL_FILE="$AWS_RDS_HOME/credential-file-path.template"
echo "$AWS_RDS_HOME"
echo "$PATH"
echo "$AWS_CREDENTIAL_FILE"
rds-delete-db-instance mydb --final-db-snapshot-identifier "mydb-daily-$(date +%Y-%m-%d)" --force -region eu-west-1
我删除了后面的空格,#!
因为它通常不使用,并且我相信没有空格脚本的可移植性会更好一些。
我"
在字符串周围添加了字符$
。"
如果使用生成的扩展$
包含任何特殊字符(包括空格),则这些字符很重要。
另外,我将三个date
命令改成了一个。使用单个date
命令更短,更可靠,以防脚本恰好在午夜之前启动。
答案3
嗯,尝试用双引号(“)将 = 右侧的位括起来吗?在我这里的小测试中,无论有没有引号,它都有效。虽然它不在 CentOS 上,但我认为 bash 在不同的 Linux 上应该表现相同。
答案4
对于我来说,这是在 Centos/使用 bash 中唯一可行的方法。
source myscript.sh
或者
. myscript.sh