用于监视/记录进程启动和停止的应用程序或脚本?


5

我希望能够启动应用程序或脚本,让它运行几个小时,然后返回并查看当时启动和停止的进程的日志。这与Activity Monitor或Top不同,它只显示“实时”视图。

像这样的事情:

<timestamp> <pid> Safari started
<timestamp> <pid> ssh started
<timestamp> <pid> ssh stopped
<timestamp> <pid> Safari stopped

有什么建议?

编辑以澄清 - 我还不知道我想要监视的进程的名称 - 我想知道哪些进程正在启动/停止。


我编辑了原始答案,为您提供动态解决方案。现在,您甚至可以在不知道其名称的情况下记录所有应用程序/进程。
E1Suave

Answers:


3

以下脚本动态构建应用程序/进程数组。这是一个优势,因为您不需要在启动之前“了解”每个进程。但是,重要的是要注意,由于此设计随着进程数量的增加,将新进程添加到阵列所需的时间越长。为了弥补这一点,脚本保持数组的内容被缓存,以便以后使用它们,从而无需将它们重新添加到数组中。

另外:如果在进程停止之前没有将应用程序/进程动态加载到数组中,则记录器将使“命令”列保持为空。当动态构建的数组基于其缓存信息构建时,这将变得越来越不可能。添加到上一点。有时“列”中可能没有显示“命令”,但它已经添加到数组中。这可能是因为某些进程像“sort”一样被删除,因为它们在脚本中使用并且会不断启动和停止(向记录器添加误报)。目前,数据将被放入文件/ command_logger中。这当然可以根据您的需要进行更改。配置文件/tmp/command_logger.plist 也可以重命名/移动但请记住它将数据保存到不断增长的App / Process数组中。

请随意使用并根据需要修改以下脚本。请记住在主要环境中运行之前使用测试环境。请享用。

测试:

   10.5.x
   10.6.x
   10.7.4

输出将包括以下内容:

  • 启动/停止
  • 时代(时间戳)
  • 约会时间
  • PID
  • 申请流程

command_logger

注意:以下脚本包含内部循环。

动态APP /过程记录器

#!/bin/bash

On="true"

TMP="/tmp/command_logger"
LOG_CONFIG="/command_logger.plist"
LOG="/command_logger"

if [[ ! -e ${TMP} ]]; then

    mkdir ${TMP}

    if [[ ! -e ${TMP}${LOG_CONFIG} ]]; then
        /usr/libexec/PlistBuddy -c "Add:Commands Dict" ${TMP}${LOG_CONFIG} > /dev/null 2>&1
    fi

elif [[ -e ${TMP} ]]; then

    if [[ ! -e ${TMP}${LOG_CONFIG} ]]; then
        /usr/libexec/PlistBuddy -c "Add:Commands Dict" ${TMP}${LOG_CONFIG} > /dev/null 2>&1
        find ${TMP} -type f ! -name '*.plist' -exec rm -f {} \;
    elif [[ -e ${TMP}${LOG_CONFIG} ]]; then
        find ${TMP} -type f ! -name '*.plist' -exec rm -f {} \;
    fi

fi

if [[ ! -e ${LOG} ]]; then
    echo -e "Status\tTimestamp\tDate/Time\t\tPID\tCommand\n" > ${LOG}
elif [[ -e ${LOG} ]]; then

    TITLE=$(head -1 ${LOG} | awk '{print $1}')

    if [[ ${TITLE} != "Status" ]]; then
        echo -e "Status\tTimestamp\tDate/Time\t\tPID\tCommand\n" > ${LOG}
    fi

fi


while [[ ${On} == "true" ]]; do
    IFS=""

    Live_Array=$(ps -Ac | sed 's/  /|/g' | sed 's/ /_/g' | sed 's/[[:digit:]]_.*[[:digit:]]_/ /g' | sed 's/:/!/' | sed 's/$/.comm/' | sed 's/^_//g' | sed 's/^|//g' | sed 's/^_//g' | sed 's/^|.*//g' | sed 's/ $//g' | sed 's/_$//g' | sed 's/|$//g' | sed 's/PID_TTY||.*//g' | awk '{print $2}' | sed 's/.*-sh.*//' | sed 's/.*CMD.*//' | sed 's/.*PID.*//' | sort -u | grep "[[:graph:]]" | tr -s "[\n]" "[,]")
    Live_Array=$(echo ${Live_Array%\,})
    IFS=","
    Live_Array_2=( $Live_Array )
    livarray=${#Live_Array_2[@]}    
    for (( liv=0; liv<${livarray}; liv++ ));
    do  


        /usr/libexec/PlistBuddy -c "Add:Commands:${Live_Array_2[$liv]} bool true" ${TMP}${LOG_CONFIG} 2> /dev/null

        Config_Array=$(/usr/libexec/PlistBuddy -c "Print:Commands" ${TMP}${LOG_CONFIG} | grep "=" | sed 's/=.*//' | sed 's/  //g' | sed 's/^.comm//' | sed 's/ $//g' | grep "[[:graph:]]" | tr -s "[\n]" "[,]")
        Config_Array_2=( $Config_Array )
        conarray=${#Config_Array_2[@]}  


        for (( con=0; con<${conarray}; con++ ));
        do  

            STRING=$(ps -Ac | sed 's/  /|/g' | sed 's/ /_/g' | sed 's/[[:digit:]]_.*[[:digit:]]_/ /g' | sed 's/:/!/'  | sed 's/$/.comm/' | sed 's/^_//g' | sed 's/^|//g' | sed 's/^_//g' | sed 's/^|.*//g' | sed 's/|_.comm/.comm/g' | sed 's/PID_TTY||.*//g' | awk '{print $2,$1}' | sed 's/.*-sh.*//' | sed 's/.*CMD.*//' | sed 's/.*PID.*//' | sort -u)
            Launched_Command=$(echo ${STRING} | awk '{print $1}' | sort -u | awk "/${Config_Array_2[$con]}/")
            PID=$(echo ${STRING} | sort -u | awk '{print $2,$1}' | awk "/${Config_Array_2[$con]}/" | sed 's/ .*//')

            if [[ ${Launched_Command} != "" ]] && [[ ${PID} != "" ]]; then

                DATE=$(date "+%m-%d-%Y %T")
                EPOCH=$(date "+%s") 

                if [[ ${Launched_Command} == ${Config_Array_2[$con]} ]] && [[ ! -e ${TMP}/${Config_Array_2[$con]}-RUNNING ]]; then          
                    echo -e "STARTED\t${EPOCH}\t${DATE}\t${PID}\t${Config_Array_2[$con]}" | sed 's/.comm$//g' | sed 's/_/ /g' | sed 's/.*sort.*//g' | sed 's/.*sed.*//g' | sed 's/awk//g'| awk '/STARTED/' >> ${LOG}
                    rm -f ${TMP}/${Config_Array_2[$con]}-STOPPED
                    touch ${TMP}/${Config_Array_2[$con]}-RUNNING
                elif [[ ${Launched_Command} == ${Config_Array_2[$con]} ]] && [[ -e ${TMP}/${Config_Array_2[$con]}-RUNNING ]]; then
                    :       
                elif [[ ${Launched_Command} == ${Config_Array_2[$con]} ]] && [[ -e ${TMP}/${Config_Array_2[$con]}-RUNNING ]]; then

                    if [[ -e ${TMP}/${Config_Array_2[$con]}-STOPPED ]]; then
                        :
                    elif [[ ! -e ${TMP}/${Config_Array_2[$con]}-STOPPED ]]; then
                        echo -e "STOPPED\t${EPOCH}\t${DATE}\t${PID}\t${Config_Array_2[$con]}" | sed 's/.comm$//g' | sed 's/_/ /g' | sed 's/.*sort.*//g' | sed 's/.*sed.*//g' | sed 's/awk//g' | awk '/STOPPED/' >> ${LOG}
                        rm -f ${TMP}/${Config_Array_2[$con]}-RUNNING
                        touch ${TMP}/${Config_Array_2[$con]}-STOPPED                    
                    fi  

                fi

            elif [[ ${Launched_Command} == "" ]] && [[ -e ${TMP}/${Config_Array_2[$con]}-RUNNING ]]; then

                if [[ -e ${TMP}/${Config_Array_2[$con]}-STOPPED ]]; then
                    :
                elif [[ ! -e ${TMP}/${Config_Array_2[$con]}-STOPPED ]]; then
                    echo -e "STOPPED\t${EPOCH}\t${DATE}\t${PID}\t${Config_Array_2[$con]}" | sed 's/.comm$//g' | sed 's/_/ /g' | sed 's/.*sort.*//g' | sed 's/.*sed.*//g' | sed 's/awk//g' | awk '/STOPPED/' >> ${LOG}
                    rm -f ${TMP}/${Config_Array_2[$con]}-RUNNING
                    touch ${TMP}/${Config_Array_2[$con]}-STOPPED                    
                fi              
            fi      
        done
    done    
done

嗨,这很棒,它给了我一些想法。但是我想让脚本告诉我任何启动的进程,我还不知道要监视的进程名称。
snowcrash09

@ snowcrash09是的,那有点不同。我想如果你想在数组中包含10个,20个,30个不同的进程/应用程序,上面的脚本仍然可以工作。我明白你的意思是“不知道”确切的具体流程/应用程序,但只要你的意图不是要监控完全未知的流程/应用程序,它仍然可以做你需要的。
E1Suave

@ snowcrash09我已经编辑了我的原始答案,为您提供动态解决方案。现在,您甚至可以在不知道其名称的情况下记录所有应用程序/进程。
E1Suave

@ snowcrash09你对新剧本有什么好运吗?
E1Suave

是的,谢谢!它似乎错误地将现有进程记录为刚启动,但我可以从这里开始。
snowcrash09

1

你看过fseventer了吗?

它允许您查看文件系统活动的图形表示,虽然它比您可能需要的更多,但它也可以列出应用程序启动和退出(然后您应该可以过滤以删除其他事件)需要)。


0

最重要的是对流程经理进行抽样。流程管理器在Unix级别上有C API,在Cocoa级别上有Obj-C API,当然还有命令PS和TOP。

我认为你要找的东西需要更多的脚本编程。我也不相信如果这样的野兽存在(我不确定)你不可能免费找到Mac应用程序。

如果您正在寻找“过程记录器”,您可以在开源社区(Google Code,Git等)中找到一个。

如果你想要旋转自己的一个; 你可能想问一下StackOverflow而不是这里。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.