Nhờ hỗ trợ của RHEL, giải pháp rõ ràng đã được phát hiện. Nó dựa trên việc sử dụng mô-đun kernel systemtap. Trích dẫn từ đây để tránh thối liên kết. Và cảm ơn bạn một lần nữa cho tất cả các lời khuyên của bạn :)
Tôi thậm chí không thể tưởng tượng rằng systemtap có thể bắt đầu ngay cả trước tập lệnh init và theo dõi quá trình khởi động. Tôi rất đánh giá cao Hỗ trợ Red Hat và cá nhân Pushpendra Chavan đã giúp đỡ với công cụ hoàn hảo này (tiếc là tôi không biết các nhà phát triển phương pháp này chính xác - nếu không tôi sẽ ghi nhận họ ngay từ đầu).
Vì vậy, chúng ta cần tạo hai tập lệnh đơn giản:
bootinit.sh:
#!/bin/sh
# Use tmpfs to collect data
/bin/echo "Mounting tmpfs to /tmp/stap/data"
/bin/mount -n -t tmpfs -o size=40M none /tmp/stap/data
# Start systemtap daemon & probe
/bin/echo "Loading bootprobe2.ko in the background. Pid is :"
/usr/bin/staprun \
/root/bootprobe2.ko \
-o /root/bootprobe2.log -D
# Give daemon time to start collecting...
/bin/echo "Sleeping a bit.."
sleep 5
# Hand off to real init
/bin/echo "Starting."
exec /sbin/init 3
và bootprobe2.1.stpđược viết bằng ngôn ngữ kịch bản hệ thống nhúng:
global ident
function get_usertime:long() {
return task_utime() + @cast(task_current(), "task_struct", "kernel<linux/sched.h>")->signal->utime;
}
function get_systime:long() {
return task_stime() + @cast(task_current(), "task_struct", "kernel<linux/sched.h>")->signal->stime;
}
function timestamp() {
return sprintf("%d %s", gettimeofday_s(), ident[pid()])
}
function proc() {
return sprintf("%d \(%s\)", pid(), execname())
}
function push(pid, ppid) {
ident[ppid] = indent(1)
ident[pid] = sprintf("%s", ident[ppid])
}
function pop(pid) {
delete ident[pid]
}
probe syscall.fork.return {
ret = $return
printf("%s %s forks %d \n", timestamp(), proc(), ret)
push(ret, pid())
}
probe syscall.execve {
printf("%s %s execs %s \n", timestamp(), proc(), filename)
}
probe syscall.open {
if ($flags & 1) {
printf("%s %s writes %s \n", timestamp(), proc(), filename)
} else {
printf("%s %s reads %s \n", timestamp(), proc(), filename)
}
}
probe syscall.exit {
printf("%s %s exit with user %d sys %d \n", timestamp(), proc(), get_usertime(), get_systime())
pop(pid())
}
<linux sched.h=""><linux sched.h="">
</linux></linux>
Để nhận được danh sách các tệp được truy cập trong quá trình khởi động ở định dạng nhật ký systemtap, chúng ta nên thực hiện như sau:
Tải xuống và cài đặt các phiên bản systemtapvà kernel debuginfogói được đặt tên TÀI SẢN (Tôi đã được cung cấp liên kết này , nhưng bạn nên sử dụng phiên bản này tốt hơn nếu bạn sử dụng CentOS);
Tạo /tmp/stapvà/tmp/stap/data
mkdir -p /tmp/stap/data
Đặt bootprobe2.1.stpvà bootinit.shvào /rootvà làm cho chúng có thể thực thi được: chmod + x / root / boot *
Chỉnh sửa bootinit.shvà thay đổi 'exec / sbin / init 3' thành 'exec / sbin / init 5' nếu 5 là runlevel mặc định của bạn.
Tạo mô-đun .ko từ bootprobe2.stp
cd /root
stap bootprobe2.1.stp -m bootprobe2 -p4
Khởi động lại.
Dừng lại grub(nhấn Esc hoặc Shift) và nhấn 'a' trên kernel mặc định. Ở cuối dòng kernel, nhập dòng sau và nhấn enter:
init=/root/bootinit.sh,
Khởi động bình thường sẽ tiếp tục. Sau khi đăng nhập, killcác stapioquy trình, sao chép bootprobe2.logra khỏi tmpfs /tmp/stap/datathư mục và unmount nó.
killall stapio
cp /tmp/stap/data/bootprobe2.log /tmp/stap/
umount /tmp/stap/data
Bây giờ hãy kiểm tra tệp /tmp/stap/bootprobe2.logtệp để biết danh sách tất cả các tệp được đọc trong khi khởi động.