问题:C++ 应用程序在关闭时更改目录权限
Problem: C++ application changes directory permissions on shutdown
我正在(一直)诊断我们在工作中使用的应用程序的一个令人费解的问题。
首先,关于这个应用的一些注意事项:
- 需要 运行 作为 root 用户
- 在 Solaris 10 操作系统上运行
- 为 C++14 编译
- 通过接收SIGTERM进行正常关机
- 将日志文件(明确设置权限为 660)写入数据目录(默认权限为 770)
应用程序 运行 运行良好,可以执行它应该执行的所有操作,直到它终止为止。终止后,应用程序将数据目录的权限从 770 更改为 660。
我的同事和我一样困惑。甚至我们的系统管理员也不明白为什么会这样。
我尝试过的事情:
- 打印语句:应用程序报告目录权限为 770,直到
exit
或 return
语句
- 检查日志记录:日志记录机制与其他几个应用程序共享,none 其中有此问题
- 运行 作为我自己:目录的权限在终止时没有改变
- 更改umask为027:目录权限仍更改为660
- 检查系统日志:sudo 和 messages 日志没有显示对目录的
chmod
的任何调用(除了那些更改回权限的调用)
由于应用程序的性质,我无法在此处提供 review/inspection 的任何代码。此外,许多标准诊断工具在相关系统上不可用。
但是,我希望这里的专家能够深入了解可能导致此问题的原因、展望未来或(理想情况下)如何解决它。
您可以使用以下简单的 dTrace 脚本从任何调用 chmod()
(或其任何变体,例如 fchmod()
或 fchmodat()
)的进程中获取堆栈跟踪:
#!/usr/sbin/dtrace -s
syscall::fchmodat:entry
{
printf{ "\nExecname: %s\n", execname );
ustack();
}
您可以按 execname 过滤以仅打印 chmod
来自您的可执行文件的调用堆栈
#!/usr/sbin/dtrace -s
syscall::fchmodat:entry
/ execname == "yourExecName" /
{
ustack();
}
您可以使用 ustack( 10 );
添加更多或更少的堆栈帧来打印,例如,10 个堆栈帧。如果您想在堆栈跟踪中使用更长或更短的函数名称,可以使用 ustack( 10, 50 );
指定字符串长度以打印 10 个堆栈帧,每个函数名称最多打印 50 个字符。
如果您的二进制文件已完全去除符号名称,您可能得不到函数名称,只有地址。
由于它是 C++ 二进制文件,您可能需要对函数名称进行分解。
获得堆栈跟踪后,您就可以开始研究到底发生了什么。
我正在(一直)诊断我们在工作中使用的应用程序的一个令人费解的问题。
首先,关于这个应用的一些注意事项:
- 需要 运行 作为 root 用户
- 在 Solaris 10 操作系统上运行
- 为 C++14 编译
- 通过接收SIGTERM进行正常关机
- 将日志文件(明确设置权限为 660)写入数据目录(默认权限为 770)
应用程序 运行 运行良好,可以执行它应该执行的所有操作,直到它终止为止。终止后,应用程序将数据目录的权限从 770 更改为 660。
我的同事和我一样困惑。甚至我们的系统管理员也不明白为什么会这样。
我尝试过的事情:
- 打印语句:应用程序报告目录权限为 770,直到
exit
或return
语句 - 检查日志记录:日志记录机制与其他几个应用程序共享,none 其中有此问题
- 运行 作为我自己:目录的权限在终止时没有改变
- 更改umask为027:目录权限仍更改为660
- 检查系统日志:sudo 和 messages 日志没有显示对目录的
chmod
的任何调用(除了那些更改回权限的调用)
由于应用程序的性质,我无法在此处提供 review/inspection 的任何代码。此外,许多标准诊断工具在相关系统上不可用。
但是,我希望这里的专家能够深入了解可能导致此问题的原因、展望未来或(理想情况下)如何解决它。
您可以使用以下简单的 dTrace 脚本从任何调用 chmod()
(或其任何变体,例如 fchmod()
或 fchmodat()
)的进程中获取堆栈跟踪:
#!/usr/sbin/dtrace -s
syscall::fchmodat:entry
{
printf{ "\nExecname: %s\n", execname );
ustack();
}
您可以按 execname 过滤以仅打印 chmod
来自您的可执行文件的调用堆栈
#!/usr/sbin/dtrace -s
syscall::fchmodat:entry
/ execname == "yourExecName" /
{
ustack();
}
您可以使用 ustack( 10 );
添加更多或更少的堆栈帧来打印,例如,10 个堆栈帧。如果您想在堆栈跟踪中使用更长或更短的函数名称,可以使用 ustack( 10, 50 );
指定字符串长度以打印 10 个堆栈帧,每个函数名称最多打印 50 个字符。
如果您的二进制文件已完全去除符号名称,您可能得不到函数名称,只有地址。
由于它是 C++ 二进制文件,您可能需要对函数名称进行分解。
获得堆栈跟踪后,您就可以开始研究到底发生了什么。