Graças ao suporte do RHEL, a solução clara foi descoberta. É baseado no uso do módulo do kernel do systemtap. Citado de aqui para evitar a podridão de links. E agradeço novamente por todos os seus conselhos:)
Eu nem imaginava que o systemtap é capaz de iniciar antes mesmo do script de inicialização e rastrear o processo de inicialização. Eu aprecio muito o Red Hat Suporte e pessoalmente Pushpendra Chavan para obter ajuda com esta ferramenta perfeita (infelizmente eu não conheço os desenvolvedores com os quais este método pertence exatamente - caso contrário, eu os creditaria em primeiro lugar).
Então, precisamos criar dois scripts simples:
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
e bootprobe2.1.stp
escritos em linguagem de script systemtap incorporada:
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>
Para receber a lista de arquivos acessados durante o processo de inicialização no formato de log systemtap, devemos implementar o seguinte:
Faça o download e instale as versões CORRECTAMENTE nomeadas de systemtap
e kernel debuginfo
packages (foi-me dado este link , mas é melhor você usar isso se você estiver no CentOS);
Crie /tmp/stap
e /tmp/stap/data
mkdir -p /tmp/stap/data
Coloque bootprobe2.1.stp
e bootinit.sh
em /root
e torne-os executáveis:
chmod + x / root / boot *
Edite bootinit.sh
e altere 'exec / sbin / init 3' para 'exec / sbin / init 5' se 5 for o seu nível de execução padrão.
Crie o módulo .ko em bootprobe2.stp
cd /root
stap bootprobe2.1.stp -m bootprobe2 -p4
Reinicie.
Pare grub
(pressione Esc ou Shift) e pressione 'a' no kernel padrão. No final da linha do kernel, digite o seguinte e pressione enter:
init=/root/bootinit.sh,
A inicialização normal será retomada. Após o login, kill
o stapio
process, copie bootprobe2.log
do diretório tmpfs
/tmp/stap/data
e desmonte-o.
killall stapio
cp /tmp/stap/data/bootprobe2.log /tmp/stap/
umount /tmp/stap/data
Agora, verifique o arquivo /tmp/stap/bootprobe2.log
para a lista de todos os arquivos que são lidos durante a inicialização.