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 systemtap
và kernel debuginfo
gó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/stap
và/tmp/stap/data
mkdir -p /tmp/stap/data
Đặt bootprobe2.1.stp
và bootinit.sh
vào /root
và làm cho chúng có thể thực thi được: chmod + x / root / boot *
Chỉnh sửa bootinit.sh
và 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, kill
các stapio
quy trình, sao chép bootprobe2.log
ra khỏi tmpfs
/tmp/stap/data
thư 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.log
tệp để biết danh sách tất cả các tệp được đọc trong khi khởi động.