如何从Ansible的ps命令结果中提取Tomcat参数并生成列表
问题描述
在Ansible中执行ps命令获取Tomcat进程信息,已将命令输出的stdout_lines存入dataresult变量,成功提取了运行Tomcat的用户列表,但无法提取catalina.home、catalina.base和logging.properties路径。希望存在多个Tomcat实例时,将这些参数分别存入对应列表,尝试的提取任务未成功,求解决。
现有相关任务与输出
1. 获取Tomcat进程的Shell任务
- name: Check running processes shell: ps aux | grep -i "[t]omcat" register: tomcat_process_cmd
2. 存储stdout_lines的任务
- name: tomcat process stdout set_fact: dataresult: "{{ tomcat_process_cmd.stdout_lines}}"
3. 已实现的用户提取任务
- name: Create dictionary for tomusers set_fact: tom_users: "{{tom_users | default([]) + [ item.split()[0]] }}" loop: "{{ dataresult }}"
4. 尝试失败的参数提取任务
- name: Create dictionary for java.util.logging.config.file set_fact: log_propss: "{{ item.split()[8] | item.0.split('=') }}" loop: "{{ dataresult }}" when: tomcat_process_cmd.stdout | regex_search('logging.config.file')
命令输出示例
tomcat 1183735 0.2 33.3 14596700 2631076 ? Sl May10 8:54 /usr/bin/java -Djava.util.logging.config.file=/opt/apache/tomcat/9.0.85/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dcom.sun.jndi.ldap.connect.pool.protocol=plain ssl -Dcom.sun.jndi.ldap.connect.pool.authentication=none simple DIGEST-MD5 -Djdk.tls.ephemeralDHKeySize=5248 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Xmx8192m -Dignore.endorsed.dirs= -classpath /opt/apache/tomcat/9.0.85/bin/bootstrap.jar:/opt/apache/tomcat/9.0.85/bin/tomcat-juli.jar -Dcatalina.base=/opt/apache/tomcat/9.0.85 -Dcatalina.home=/opt/apache/tomcat/9.0.85 -Djava.io.tmpdir=/opt/apache/tomcat/9.0.85/temp org.apache.catalina.startup.Bootstrap start
期望输出格式
users: [userA, userB] catalinahome: [catalinahome1, catalinahome2] catalinabase: [catalinabase1, catalinabase2] loggingprops: [logpath1, logpath2]
解决方案
问题核心是stdout_lines按行拆分,而Tomcat启动参数分散在多行,无法按单行直接处理。以下是两种可行解决方法:
方法一:合并进程行后精准提取
先将同一Tomcat进程的多行输出合并为单条字符串,再针对每个进程提取对应参数,保证用户与参数严格对应:
- name: 合并同一进程的多行输出 set_fact: tomcat_processes: "{{ tomcat_processes | default([]) + [current_process] }}" vars: current_process: >- {% if tomcat_processes is undefined %} {{ item }} {% else %} {{ tomcat_processes[-1] + ' ' + item }} {% endif %} loop: "{{ tomcat_process_cmd.stdout_lines }}" when: >- tomcat_processes is undefined or not item matches '^\w+\s+\d+' - name: 提取所有Tomcat实例的参数 set_fact: tom_users: "{{ tom_users | default([]) + [item | regex_search('^([\\w-]+)\\s+', '\\1') | first] }}" catalinahome: "{{ catalinahome | default([]) + [item | regex_search('-Dcatalina\\.home=([^\\s]+)', '\\1') | first] }}" catalinabase: "{{ catalinabase | default([]) + [item | regex_search('-Dcatalina\\.base=([^\\s]+)', '\\1') | first] }}" loggingprops: "{{ loggingprops | default([]) + [item | regex_search('-Djava\\.util\\.logging\\.config\\.file=([^\\s]+)', '\\1') | first] }}" loop: "{{ tomcat_processes }}"
方法二:直接从完整stdout提取(简洁版)
若无需严格绑定用户与参数的对应关系,可直接从整个stdout中提取所有匹配的参数:
- name: 提取用户列表 set_fact: tom_users: "{{ tomcat_process_cmd.stdout | regex_findall('^([\\w-]+)\\s+\\d+', '\\1') }}" - name: 提取catalina.home列表 set_fact: catalinahome: "{{ tomcat_process_cmd.stdout | regex_findall('-Dcatalina\\.home=([^\\s]+)', '\\1') }}" - name: 提取catalina.base列表 set_fact: catalinabase: "{{ tomcat_process_cmd.stdout | regex_findall('-Dcatalina\\.base=([^\\s]+)', '\\1') }}" - name: 提取logging.properties路径列表 set_fact: loggingprops: "{{ tomcat_process_cmd.stdout | regex_findall('-Djava\\.util\\.logging\\.config\\.file=([^\\s]+)', '\\1') }}"
说明
- 正则表达式
-Dcatalina\.home=([^\s]+)会匹配-Dcatalina.home=后直到空格的所有字符,即完整路径。 regex_findall直接返回所有匹配结果形成列表,无需循环拼接。
内容的提问来源于stack exchange,提问作者maddy
相关产品推荐
相关产品推荐

