远程SSH执行带通配符的sudo grep命令失败,求解决方法
这个问题我之前也碰到过,核心原因是通配符*的解析权限不匹配,咱们一步步拆解:
为什么本地能运行,远程不行?
当你在本地执行$ sudo grep login /var/log/nginx/access.log*时,本地shell会先解析通配符*,把它展开成目录下所有匹配的日志文件名(比如access.log、access.log.1),然后再把展开后的文件名传给sudo grep,所以能正常工作。
但远程执行$ ssh remote-server 'sudo grep login /var/log/nginx/access.log*'时,单引号会阻止本地shell解析*,这个通配符会直接传给远程服务器的普通用户shell。而普通用户没有访问/var/log/nginx目录的权限,shell没法展开*,只能把/var/log/nginx/access.log*当成一个完整的文件名,自然会提示“文件不存在”。
解决方案
以下几种方法都能解决,选你顺手的就行:
方法1:让root shell解析通配符
通过sudo sh -c让root启动的shell来处理通配符,root有权限访问日志目录,能正确展开*:
ssh remote-server 'sudo sh -c "grep login /var/log/nginx/access.log*"'
这里的双引号是让root shell识别通配符,外层的单引号确保整个命令完整传给远程服务器。
方法2:强制分配伪终端(适合需要输入sudo密码的场景)
如果你的sudo需要输入密码,加上-t选项强制ssh分配伪终端,同时也能让sudo的shell正确处理通配符:
ssh -t remote-server 'sudo grep login /var/log/nginx/access.log*'
执行后会弹出输入远程服务器sudo密码的提示,输入后就能正常运行。
方法3:通过su切换到root执行
和方法1原理类似,用sudo su -c让root执行命令:
ssh remote-server 'sudo su -c "grep login /var/log/nginx/access.log*"'
验证
执行完上面的命令后,你应该就能看到所有包含login关键字的日志行,从中提取登录IP就行啦。
内容的提问来源于stack exchange,提问作者jinzoo

