kubernetes bash警告:由文件结尾分隔(wanted `!')

5f0d552i  于 2023-10-17  发布在  Kubernetes
关注(0)|答案(2)|浏览(99)

我有一个K8S CronJob,可以将文件上传到远程SFTP服务器。为了确保在发生上载错误时作业不会运行完成,我添加了错误处理逻辑。然而,逻辑给出了如下错误:

Starting-BACKUP
2023-09-27T07:39:01.384+0000    reading password from standard input
Enter password for mongo user:
/configmap/backup.sh: line 18: warning: here-document at line 9 delimited by end-of-file (wanted `!')
/configmap/backup.sh: line 19: syntax error: unexpected end of file
Database backup was successful

我尝试处理的错误发生在SFTP服务器容量已满时。在这种情况下,理想情况下,作业不应该运行到完成,并且关联的容器应该失败,退出代码为1。当由于空间不足问题导致上载失败时,作业的日志输出如下所示:

Starting-BACKUP
2023-09-26T13:25:01.406+0000    reading password from standard input
Enter password for mongo user:
Database backup was successful
Warning: Permanently added '[ftp.mycompany.com]:2020,[10.XX.XXX.XXX]:xxxx' (RSA) to the list of known hosts.     
Connected to ftp.mycompany.com.
Changing to: /oasys
sftp>   put labs-instance_20230926132501.gzip
Uploading labs-instance_20230926132501.gzip to /oasys/labs-instance_20230926132501.gzip
remote open("/oasys/labs-instance_20230926132501.gzip"): Failure
sftp>   bye
BackUp file labs-instance_20230926132501.gzip was successfully transfered
BackUp file labs-instance_20230926132501.gzip was deleted

当前,尽管实际上传不成功,但作业仍运行到完成:

NAME                       COMPLETIONS   DURATION   AGE
labs-backupjob-28262274    1/1           15s        7m42s

作业创建的pod的最终状态也是Completed

NAME                                   READY   STATUS      RESTARTS         AGE
labs-backupjob-28262286--1-s6g72       0/1     Completed   0                38s

CronJob和bash脚本如下:

apiVersion: v1
    kind: ConfigMap
    metadata:
      name: backup-config
data:
  backup.sh: |-
    #!/bin/bash 
    set -e  # Exit on error

    echo "Starting-BACKUP"
    TIMESTAMP=$(date +"%Y%m%d%H%M%S")
    BACKUP_FILE_NAME="labs-instance_$TIMESTAMP.gzip"
    echo $MONGODB_ROOT_PASSWORD | mongodump --uri="mongodb://mongodb-prom:27017" --username="root" --authenticationDatabase="admin" --gzip --archive="$BACKUP_FILE_NAME" --quiet 
    echo "Database backup was successful"
    if ! sshpass -e sftp -o StrictHostKeyChecking=no -P XXXX [email protected]:/oasys << !
    put $BACKUP_FILE_NAME
    bye
    !; then
      echo "Error uploading file to SFTP server"
      exit 1 
    fi
    echo "BackUp file $BACKUP_FILE_NAME was successfully transfered"
    rm $BACKUP_FILE_NAME
    echo "BackUp file $BACKUP_FILE_NAME was deleted"    

---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: labs-backupjob
spec:
  schedule: "*/3 * * * *"
  concurrencyPolicy: Forbid
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: mongodb-backup
            image: registry.mycompany.com/oasys/devops/docker-images/mongosh:6.0
            imagePullPolicy: Always            
            command: ["/configmap/backup.sh"]
            env:
            - name: MONGODB_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mongodb-labs
                  key: mongodb-root-password
            - name: SSHPASS
              valueFrom:
                secretKeyRef:
                  name: sftp-password
                  key: sftp-backup-password
            volumeMounts:
                - name: backup-volume
                  mountPath: /configmap
          volumes:
            - name: backup-volume
              configMap:
                name: backup-config    
                defaultMode: 0777
          restartPolicy: Never
          imagePullSecrets:
            - name: regcred
      backoffLimit: 0

我错过了什么?

zi8p0yeb

zi8p0yeb1#

Here-docs可能会很痛苦,特别是如果你需要保持缩进。你把它作为测试条件,这会导致问题。!; then会混淆解析器,至少在我的测试系统上是这样。

$: cat tst
#!/bin/bash

if cat << !
foo 1
!
then echo ok on 1; else echo no on 1; fi

cat << !
foo 2
!
if [[ 0 == $? ]]; then echo ok on 2; else echo no on 2; fi

if cat << !
foo 3
!; then echo ok on 3; else echo no on 3; fi

echo never gets here

$: ./tst
foo 1
ok on 1
foo 2
ok on 2
./tst: line 18: warning: here-document at line 13 delimited by end-of-file (wanted `!')
./tst: line 19: syntax error: unexpected end of file

我强烈建议使用scp,而不是任何ftp,甚至sftp。我经常这么做,比如这里,这里,还有这里。实际上,CLI ftp * 的每一种风格都希望是交互式的 *。它假设您正在查看屏幕,并将处理任何出错的情况,因此如果您的某个命令失败,它通常不会向操作系统返回错误。
如果你能建立公钥信任,那就容易多了。

if ! scp "$BACKUP_FILE_NAME" [email protected]:/oasys/
    then
      echo "Error uploading file"
      exit 1
    fi

这在YAML中工作得很好,YAML不能使用前导制表符,而here-docs可以用<<-去除前导制表符缩进,但不能处理前导空格。scp报告任何失败并带有错误代码,并且可以很容易地检查。只要确保你得到正确的目标路径,如果它是不同的。
如果公钥信任不是一个选项,请参阅this post以获得替代方案,例如使用sshpass(尽管这将密码留在CLI上,因此可能在历史记录,系统日志,任何作业日志等中)甚至curl(允许您在stdin上提供它)。
同样,也有替代here-docs的方法,以及重用和动态格式化输入列表的方法。或许其中有些会对某人有用-

$: cat tst
#!/bin/bash

if cat; then echo "> literal ok"; else echo no; fi <<<"maybe you prefer literals -
put ${BACKUP_FILE_NAME:-some_file}
bye";

# if reusing commands and/or concerned about whitespace, I like an array
cmds=(
  "put ${BACKUP_FILE_NAME:-some_file}"
  bye
)

if cat <<<"$( printf "  %s\n" "${cmds[@]}" )"; then echo "> Indented command substitution ok"; else echo no; fi

( IFS=$'\n'; if cat <<<"${cmds[*]^}"; then echo "> Capitalized IFS hack ok"; else echo no; fi; )

printf "\t%s\n" "${cmds[@]}" | if cat; then echo "> tabbed pipe ok"; else echo no; fi

if cat; then echo "> bracketed Process substitution ok"; else echo no; fi < <( printf "[%s]\n" "${cmds[@]}" )

if cat << !
$( printf "%s\n" "${cmds[@]^^}" )
!
then echo "> here-doc up-cased command substitution ok"; else echo no; fi

( IFS=$'\n'
if cat << !
${cmds[*]}
!
then echo "> here-doc with IFS hack ok"; else echo no; fi; )

当运行时,生成:

$: ./tst
maybe you prefer literals -
put some_file
bye
> literal ok
  put some_file
  bye
> Indented command substitution ok
Put some_file
Bye
> Capitalized IFS hack ok
        put some_file
        bye
> tabbed pipe ok
[put some_file]
[bye]
> bracketed Process substitution ok
PUT SOME_FILE
BYE
> here-doc up-cased command substitution ok
put some_file
bye
> here-doc with IFS hack ok
brgchamk

brgchamk2#

这就是我如何得到它的工作-我添加了sftp选项-oBatchMode=no -b -。只有这样,如果sftp命令出错,sftp才会以状态1退出。否则,退出状态始终为0。修改后的代码如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: backup-config
data:
  backup.sh: |-
    #!/bin/bash 
    set -e  # Exit on error
echo "Starting-BACKUP"
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
BACKUP_FILE_NAME="labs-instance_$TIMESTAMP.gzip"
echo $MONGODB_ROOT_PASSWORD | mongodump --uri="mongodb://mongodb-prom:27017" --username="root" --authenticationDatabase="admin" --gzip --archive="$BACKUP_FILE_NAME" --quiet 
echo "Database backup was successful"
sshpass -e sftp -o StrictHostKeyChecking=no -oBatchMode=no -b - -P XXXX [email protected]:/oasys << !
  put $BACKUP_FILE_NAME
  bye
!
echo "BackUp file $BACKUP_FILE_NAME was successfully transfered"
rm $BACKUP_FILE_NAME
echo "BackUp file $BACKUP_FILE_NAME was deleted"

相关问题