ssh ls *|wc -l 返回统计值

本文介绍了一款用于通过SSH连接远程服务器并批量统计指定目录下匹配特定模式的文件数量的Shell脚本。该脚本能够遍历一系列IP地址,针对每个服务器上的指定路径进行文件数量的统计。

ssh ls *|wc -l 返回统计值

#!/bin/sh

 for i in {2..25}
 do
        ip=10.161.21.$i
        echo $ip

        t=`ssh unicomlabs@$ip    "ls /home/unicomlabs/qq*|wc -l"`;
        echo "t=$t"
       #echo $ip >> ip10.161.21.txt;  echo "####################################################" >> ip10.161.21.txt;echo "####################################################" >> ip10.161.21.txt
        #t2=`ssh unicomlabs@$ip   cat /home/unicomlabs/ip2.txt|wc -l`;
        #t3=`ssh unicomlabs@$ip   cat /home/unicomlabs/ip3.txt|wc -l`;
        #t4=`ssh unicomlabs@$ip   cat /home/unicomlabs/ip4.txt|wc -l`;
        #t5=`ssh unicomlabs@$ip   cat /home/unicomlabs/ip5.txt|wc -l`;
        #t=$(($t1+$t2+$t3+$t4+$t5))
        #echo "$ip=$t";


done

<think>我们面对的问题是:文件检查失败,错误信息为“Cannot invoke method trim() on null object”,同时需要将命令`sudo docker exec ${containerName} sh -c 'ls ${checkDir} | wc -l'`的返回结果(即目录中的文件数量)作为变量输出。 ### 问题分析 1. **空对象调用trim()错误**:这个错误通常发生在Groovy脚本中尝试在一个`null`对象上调用`trim()`方法。在我们的场景中,可能是由于变量`containerName`或`checkDir`为`null`导致的。 2. **命令执行目标**:我们需要执行一个Docker命令来检查容器中某个目录下的文件数量,并将结果作为变量输出。 ### 解决方案 #### 第一步:修复空对象错误 我们需要确保在执行命令之前,变量`containerName`和`checkDir`都不为`null`,并且已经进行了适当的清理(如去除空格等)。我们可以使用Groovy的安全导航操作符(`?.`)或显式的空值检查。 **修复代码示例**: ```groovy // 获取变量,如果为null则设为空字符串 def containerName = vars.get("containerName") ?: "" def checkDir = vars.get("checkDir") ?: "" // 去除空格(注意:如果为空字符串,trim()后还是空字符串,不会报错) containerName = containerName.trim() checkDir = checkDir.trim() // 检查必要参数是否为空 if (!containerName) { throw new Exception("containerName 变量不能为空") } if (!checkDir) { throw new Exception("checkDir 变量不能为空") } ``` #### 第二步:执行Docker命令并获取输出 在JMeter中,我们可以使用`SSH Command`采样器或`OS Process Sampler`来执行系统命令。这里我们假设使用`JSR223 Sampler`(Groovy脚本)通过执行Shell命令来获取结果。 **注意**:在Groovy脚本中执行系统命令,我们可以使用`'command'.execute().text`,但是需要注意权限问题(如sudo)和命令的完整路径。 由于命令中使用了`sudo`,我们需要确保JMeter进程有权限执行sudo而不需要密码。或者我们可以考虑将JMeter用户添加到docker用户组,从而避免使用sudo。 **替代方案(避免sudo)**:将运行JMeter的用户添加到docker用户组(推荐): ```bash sudo usermod -aG docker $USER ``` 然后,我们就可以不使用sudo来执行docker命令。 **执行命令的Groovy脚本**(在JSR223 Sampler中): ```groovy import org.apache.jmeter.util.JMeterUtils // 获取变量(已经过非空处理) def containerName = vars.get("containerName") def checkDir = vars.get("checkDir") // 构建命令 def command = "docker exec ${containerName} sh -c 'ls ${checkDir} | wc -l'".toString() try { // 执行命令并获取输出 def process = command.execute() process.waitFor() def output = process.text.trim() // 输出应该是数字,如果是空目录则输出0,注意错误处理 if (output.isNumber()) { // 将结果保存为JMeter变量,例如fileCount vars.put("fileCount", output) log.info("目录 ${checkDir} 中的文件数量为: ${output}") } else { log.error("命令执行失败,输出不是数字: ${output}") // 可以进一步解析错误,比如输出可能是错误信息 vars.put("fileCount", "-1") // 用-1表示错误 } } catch (Exception e) { log.error("执行命令出错: ", e) vars.put("fileCount", "-1") } ``` #### 第三步:处理命令执行的潜在问题 1. **目录不存在或容器不存在**:命令执行可能会返回错误信息,而不是数字。因此,我们尝试将输出转换为数字,如果失败则记录错误。 2. **命令执行权限**:确保JMeter有权限执行docker命令(如上述将用户加入docker组)。 ### 完整示例(JSR223 Sampler) 将以下代码放入JSR223 Sampler(选择Groovy语言): ```groovy // 安全获取变量并去除空格 def containerName = (vars.get("containerName") ?: "").trim() def checkDir = (vars.get("checkDir") ?: "").trim() // 检查是否为空 if (!containerName) { log.error("containerName 为空") throw new Exception("containerName 不能为空") } if (!checkDir) { log.error("checkDir 为空") throw new Exception("checkDir 不能为空") } try { // 构建命令(不使用sudo,因为我们已将用户加入docker组) def command = "docker exec ${containerName} sh -c 'ls -A \"${checkDir}\" | wc -l'".toString() log.info("执行命令: " + command) // 执行命令 def process = command.execute() process.waitFor() // 获取输出 def output = process.text.trim() // 检查输出是否是整数 if (output ==~ /^\d+$/) { vars.put("fileCount", output) log.info("文件数量: ${output}") } else { log.error("命令输出异常: ${output}") // 获取错误流 def error = process.err.text if (error) { log.error("错误信息: ${error}") } vars.put("fileCount", "-1") } } catch (Exception e) { log.error("命令执行异常: ", e) vars.put("fileCount", "-1") } ``` ### 注意事项 1. **目录路径中的空格**:如果`checkDir`可能包含空格,我们在命令中使用了双引号`\"${checkDir}\"`来包裹路径,确保命令正确解析。 2. **隐藏文件**:命令`ls -A`包括隐藏文件(但不包括`.`和`..`),如果需要包括所有文件,这样做是合适的。 3. **错误处理**:我们捕获了异常,并且检查了命令的退出状态(通过`process.waitFor()`),同时读取了错误流(`process.err.text`)以便记录错误。 4. **性能**:在JMeter中执行系统命令会消耗资源,建议仅在必要时使用,并注意命令执行时间。 ### 如何在JMeter中使用 1. 将上述脚本放入JSR223 Sampler。 2. 确保JMeter运行用户有权限执行docker命令(无需sudo)。 3. 提前设置好`containerName`和`checkDir`变量(例如通过用户定义的变量或前置处理器)。 4. 后续可以通过`${fileCount}`引用文件数量。 ### 相关问题 1. 如果容器名称或目录路径中包含特殊字符(如空格、引号等),应如何处理? 2. 如何优化在JMeter中执行系统命令的性能? 3. 除了使用`ls | wc -l`,还有哪些方法可以获取目录中的文件数量? </think>### 解决文件检查失败问题并获取目录文件数 我将逐步解决两个核心问题: 1. 修复 `Cannot invoke method trim() on null object` 错误 2. 正确获取 Docker 容器目录文件数并输出为变量 --- ### 一、修复空对象错误 问题发生在尝试对 `null` 值调用 `trim()` 方法,主要发生在变量 `${containerName}` 或 `${checkDir}` 为空时。 **修复方案**: ```groovy // 安全获取并处理参数 def containerName = vars.get("containerName") ?: "" def checkDir = vars.get("checkDir") ?: "" // 防御性处理:空值检查 + trim() containerName = containerName ? containerName.trim() : "" checkDir = checkDir ? checkDir.trim() : "" // 验证必要参数 if (!containerName) { throw new Exception("容器名称不能为空") } if (!checkDir) { throw new Exception("检查目录不能为空") } ``` **关键点说明**: 1. **空值合并操作符 `?:`**:为变量提供默认空字符串值[^1] 2. **三元表达式安全调用**:`variable ? variable.trim() : ""` 避免空指针 3. **前置校验**:执行命令前验证必要参数 --- ### 二、获取目录文件数并输出变量 使用增强命令获取容器目录文件数,并处理特殊场景: ```groovy // 构建安全命令(处理特殊字符) def cmd = """ sudo docker exec ${containerName.replace("'", "'\\''")} \ sh -c 'ls -A "${checkDir.replace("'", "'\\''")}" 2>/dev/null | wc -l' """ // 执行命令 def process = cmd.execute() process.waitFor() // 获取输出并转换为变量 def fileCount = process.text.trim() // 验证输出是否为数字 if (fileCount ==~ /^\d+$/) { vars.put("DIR_FILE_COUNT", fileCount) log.info("目录文件数: ${fileCount}") } else { log.error("无效输出: ${fileCount}") vars.put("DIR_FILE_COUNT", "-1") // 错误标识 } ``` **增强处理**: 1. **路径安全转义**:`replace("'", "'\\''")` 处理单引号[^2] 2. **错误重定向**:`2>/dev/null` 忽略目录不存在的错误 3. **隐藏文件统计**:`ls -A` 包含隐藏文件但不包含 `.` 和 `..` 4. **输出验证**:正则验证 `^\d+$` 确保输出为纯数字 --- ### 三、完整解决方案(JSR223 Sampler) ```groovy try { // ===== 1. 参数安全处理 ===== def containerName = (vars.get("containerName") ?: "").trim() def checkDir = (vars.get("checkDir") ?: "").trim() if (!containerName) throw new Exception("容器名称未设置") if (!checkDir) throw new Exception("检查目录未指定") // ===== 2. 构建安全命令 ===== def safeContainer = containerName.replace("'", "'\\''") def safeDir = checkDir.replace("'", "'\\''") def cmd = "sudo docker exec ${safeContainer} " + "sh -c 'ls -A \"${safeDir}\" 2>/dev/null | wc -l'" // ===== 3. 执行并处理输出 ===== def output = cmd.execute().text.trim() if (output.isNumber()) { vars.put("DIR_FILE_COUNT", output) log.info("${checkDir} 文件数: ${output}") } else { log.warn("目录可能不存在: ${output}") vars.put("DIR_FILE_COUNT", "0") } } catch (Exception e) { log.error("执行失败: " + e.getMessage()) vars.put("DIR_FILE_COUNT", "-1") } ``` **使用说明**: 1. 将脚本放入 JMeter 的 **JSR223 Sampler** 2. 通过 `${DIR_FILE_COUNT}` 引用目录文件数 3. 返回值说明: - `≥0`:实际文件数量 - `0`:空目录或目录不存在 - `-1`:执行错误 --- ### 四、验证与调试 **测试用例**: ```groovy // 模拟空目录 vars.put("containerName", "my-container") vars.put("checkDir", "/empty/dir") // 预期输出: DIR_FILE_COUNT = 0 // 模拟特殊字符路径 vars.put("checkDir", "/path/with'space and'quote") // 预期命令: sudo docker exec ... 'ls -A "/path/with'\''space and'\''quote" ...' ``` **调试建议**: 1. 启用 `log.info(cmd)` 检查生成的命令 2. 测试容器内手动执行相同命令 3. 使用 `docker exec -it ${containerName} sh` 进入容器验证目录 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值