【问题标题】:Ansible: Error executing shell script on targetAnsible:在目标上执行 shell 脚本时出错
【发布时间】:2021-03-02 19:40:17
【问题描述】:

我必须在我的剧本末尾在 RHEL 7 目标服务器上运行一个 shell 脚本。 我可以在目标上手动执行脚本,但是通过 ansible 会出错,如下所示:

TASK [oracle_si_grid_install : executing the script to modify template values] **************************************************************************************************************
FAILED - RETRYING: executing the script to modify template values (3 retries left).
FAILED - RETRYING: executing the script to modify template values (2 retries left).
FAILED - RETRYING: executing the script to modify template values (1 retries left).

致命:[10.210.224.87]:失败! => {"attempts": 3, "changed": true, "cmd": "/tmp/modify_db_template.sh", "delta": "0:00:00.113423", "end": "2020-11-19 12:21:18.642239”、“msg”:“非零返回码”、“rc”:2、“start”:“2020-11-19 12:21:18.528816”、“stderr”:“/tmp/ modify_db_template.sh:第 9 行:意外标记附近的语法错误 &lt;'\n/tmp/modify_db_template.sh: line 9: while IFS= read -r line; do echo "processing line: $line"; sed -i "s|$line| |g" $DBCA_TEMPLATE; 完成<'", "/tmp/modify_db_template.sh: line 9: while IFS= read -r line; do echo "processing line: $line"; sed -i" s|$line| |g" $DBCA_TEMPLATE; 完成

该模块的 Ansible 代码如下:

- name: executing the script to modify template values
  shell: "/tmp/{{ modify_template }}"
  register: modtemp
  retries: 3
  delay: 2
  until: modtemp.rc == 0
  become: True
  become_user: "{{ db_user }}"
  become_method: su

请注意,我确实使用了 script / shell 并添加了 args: executable 参数,但它们也失败了。 shell脚本如下:

if [ ! -e /tmp/benv.sh ]
then
  echo "No Env file found"
  exit -1
fi

source /tmp/benv.sh

while IFS= read -r line; do echo "processing line: $line"; sed -i "s|$line|         <initParam name=\"sga_target\" value=\"${SGA_TARGET}\" unit=\"MB\"/>|g" $DBCA_TEMPLATE; done < <(grep 'name="sga_target" value=' $DBCA_TEMPLATE)
while IFS= read -r line; do echo "processing line: $line"; sed -i "s|$line|         <initParam name=\"processes\" value=\"${DB_PROCESSES}\"/>|g" $DBCA_TEMPLATE; done < <(grep 'name="processes" value=' $DBCA_TEMPLATE)
while IFS= read -r line; do echo "processing line: $line"; sed -i "s|$line|         <initParam name=\"pga_aggregate_target\" value=\"${PGA_TARGET}\" unit=\"MB\"/>|g" $DBCA_TEMPLATE; done < <(grep 'name="pga_aggregate_target" value=' $DBCA_TEMPLATE)
#while IFS= read -r line; do echo "processing line: $line"; sed -i "s|$line|         <fileSize unit=\"KB\">${REDO_SIZE}</fileSize>|g" $DBCA_TEMPLATE; done < <(grep '<fileSize unit="KB">204800</fileSize>' $DBCA_TEMPLATE)
# if there are no disks for FRA, then recovery destination and related init params will be removed from template
while IFS= read -r line; do echo "processing line: $line"; [ -n "${ORA_LOG}" ] && sed -i "s|$line|         <initParam name=\"db_recovery_file_dest_size\" value=\"${RECOVERY_SIZE}\" unit=\"MB\"/>|g" $DBCA_TEMPLATE || sed -i "\|${line}|d" $DBCA_TEMPLATE; done < <(grep 'name="db_recovery_file_dest_size" value=' $DBCA_TEMPLATE )
while IFS= read -r line; do echo "processing line: $line"; [ -z "${ORA_LOG}" ] && sed -i "\|${line}|d" $DBCA_TEMPLATE; done < <(grep 'name="archive_lag_target" value=' $DBCA_TEMPLATE)
while IFS= read -r line; do echo "processing line: $line"; [ -z "${ORA_LOG}" ] && sed -i "\|${line}|d" $DBCA_TEMPLATE; done < <(grep 'name="control_file_record_keep_time" value=' $DBCA_TEMPLATE)
# if there is no BACKUP disk, then noarchivelog will be assumed
# if Oracle Cloud Backup module is used, then ORA_BACKUP must have a fake disk specified
while IFS= read -r line; do echo "processing line: $line"; [ -z "${ORA_LOG}" ] && sed -i "s|$line|         <archiveLogMode>false</archiveLogMode>|g" $DBCA_TEMPLATE ; done < <(grep '<archiveLogMode>true</archiveLogMode>' $DBCA_TEMPLATE)

手动,它按预期运行

[oracle@ansible-poc6 ~]$ /tmp/modify_db_template.sh
processing line:          <initParam name="sga_target" value="9536" unit="MB"/>
processing line:          <initParam name="processes" value="1339"/>
processing line:          <initParam name="pga_aggregate_target" value="1906" unit="MB"/>
processing line:          <initParam name="db_recovery_file_dest_size" value="" unit="MB"/>
processing line:          <initParam name="archive_lag_target" value="900"/>
processing line:          <initParam name="control_file_record_keep_time" value="38"/>
processing line:          <archiveLogMode>true</archiveLogMode>
[oracle@ansible-poc6 ~]$ echo $SHELL
/bin/bash

/tmp/benv.sh 的内容

export DB_SID=oratest
export COMPLIANCE_TYPE="sox"
export CRITICALITY="critical"
export ORA_CHAR=AL32UTF8
export ORA_NCHAR=AL16UTF16
# storage vars - if more than one disk, then list separate with whitespace
export ORA_OCR="/dev/sdb"
export ORA_DATA="/dev/sdd /dev/sde /dev/sdf"
export ORA_SWAP=""
export ORA_LOG="/dev/sdg"
# constants
export BASE_ORA=/u01/app/oracle
export HOME_ORA=/u01/app/oracle/product/19/dbee_1
export HOME_CRS=/u01/app/19/grid
# template file
DBCA_TEMPLATE="/u01/app/oracle/product/19/dbee_1/assistants/dbca/templates/dbca-create-seeded.dbc"

# calculations
MEMORY=$(eval "echo $((`grep 'MemTotal:' /proc/meminfo | awk '{print $2}'` / 1024))") # [MB]
[ -n "${ORA_OCR}" ] && DB_MEMORY=$(eval "(( `echo $((MEMORY - 3072))` < `echo $((MEMORY * 8/10))` )) && echo $((MEMORY - 3072)) || echo $((MEMORY * 8/10))") || DB_MEMORY=$(eval "(( `echo $((MEMORY - 2048))` < `echo $((MEMORY * 8/10))` )) && echo $((MEMORY - 2048)) || echo $((MEMORY * 8/10))") # [MB]
DB_PROCESSES=$(eval "(( `echo $(( (DB_MEMORY+512) * 1000000 / 9868951 ))` < 320 )) && echo '320' || ((( `echo $(( (DB_MEMORY+512) * 1000000 / 9868951 ))` > 20000 )) && echo '20000' || echo $(( (DB_MEMORY+512) * 1000000 / 9868951 )))")
SGA_TARGET=$(eval "(( `echo $((DB_MEMORY * 75/100))` < 768 )) && echo '768' || echo $((DB_MEMORY * 75/100))") # [MB]
SGA_TARGET=$(eval "
if     [ ${SGA_TARGET} -le 1024 ]; then (( `echo $((SGA_TARGET%4))` > 0 )) && echo $((4-SGA_TARGET%4+SGA_TARGET)) || echo $SGA_TARGET;
elif   [ ${SGA_TARGET} -le 8192 ]; then (( `echo $((SGA_TARGET%16))` > 0 )) && echo $((16-SGA_TARGET%16+SGA_TARGET)) || echo $SGA_TARGET;
elif  [ ${SGA_TARGET} -le 16384 ]; then (( `echo $((SGA_TARGET%32))` > 0 )) && echo $((32-SGA_TARGET%32+SGA_TARGET)) || echo $SGA_TARGET;
elif  [ ${SGA_TARGET} -le 32768 ]; then (( `echo $((SGA_TARGET%64))` > 0 )) && echo $((64-SGA_TARGET%64+SGA_TARGET)) || echo $SGA_TARGET;
elif  [ ${SGA_TARGET} -le 65536 ]; then (( `echo $((SGA_TARGET%128))` > 0 )) && echo $((128-SGA_TARGET%128+SGA_TARGET)) || echo $SGA_TARGET;
elif [ ${SGA_TARGET} -le 131072 ]; then (( `echo $((SGA_TARGET%256))` > 0 )) && echo $((256-SGA_TARGET%256+SGA_TARGET)) || echo $SGA_TARGET;
else
(( `echo $((SGA_TARGET%512))` > 0 )) && echo $((512-SGA_TARGET%512+SGA_TARGET)) || echo $SGA_TARGET;
fi
") # [MB]
PGA_TARGET=$(eval "(( `echo $((DB_MEMORY * 15/100))` < 384 )) && echo '384' || echo $((DB_MEMORY * 15/100))") # [MB] pga over 20% will cause ORA-700
HUGEPAGES=$(eval "echo $((SGA_TARGET/2 + 1))")
SWAP_SIZE=$(eval "((`echo $((MEMORY - (HUGEPAGES * 2) + 4))` < 16384)) && echo $((MEMORY - (HUGEPAGES * 2) + 4)) || echo '16384'") # [MB]

感谢您的时间和帮助。 提前致谢

-- JK

【问题讨论】:

  • 您是否以与手动运行脚本时相同的用户身份运行 playbook?
  • 另外,你有#!在脚本的顶部?
  • 是的,我在目标上以 oracle 用户身份运行它。刚刚添加了#!但它仍然失败:(
  • 来源/tmp/benv.sh 文件的内容是什么?您的脚本是否依赖于目标机器上登录环境中设置的任何变量? Ansible 默认使用 sh 没有任何登录初始化:你是否尝试将 executable param 设置为 bash ?
  • 您需要根据环境添加#!/bin/bash 或#!/bin/st

标签: linux bash shell ansible


【解决方案1】:

引用模块shell

"...通过远程节点上的 shell (/bin/sh) 运行命令。"

您在 /bin/bash 中说 “手动,它按预期运行”。下面的错误很可能是在bin/sh中运行命令造成的。

"msg": "non-zero return code", "rc": 2
"stderr": "/tmp/modify_db_template.sh: line 9: syntax error near unexpected token <' ...

在 Ansible 中,使用参数 executable 并在 /bin/bash 中运行命令。例如

- name: executing the script to modify template values
  shell: "/tmp/{{ modify_template }}"
  args:
    executable: /bin/bash
  register: modtemp
  retries: 3
  delay: 2
  until: modtemp.rc == 0
  become: True
  become_user: "{{ db_user }}"
  become_method: su

【讨论】:

  • 我做到了,但仍然没有用:- name: executing the script to modify template values raw: "/tmp/{{ modify_template }}" args: executable: /usr/bin/bash register: modtemp retries: 3 delay: 2 until: modtemp.rc == 0 become: True become_user: "{{ db_user }}" become_method: su
  • 然后找出手动运行和在 Ansible 中运行的区别。不要将代码放入注释中。使用当前代码和当前错误消息更新您的问题。将其设为mcve 并将问题隔离为几行。删除不相关的代码部分 1) 删除测试 2) 保留导致问题的单个 while 行 3) 减少复杂的 sed 参数...换句话说,使其最小化,但完整且可重现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多