{"id":165,"date":"2012-07-09T02:03:22","date_gmt":"2012-07-09T02:03:22","guid":{"rendered":"http:\/\/www.selinuxplus.com\/?p=165"},"modified":"2013-06-07T07:43:21","modified_gmt":"2013-06-07T07:43:21","slug":"proc_watch","status":"publish","type":"post","link":"http:\/\/www.selinuxplus.com\/?p=165","title":{"rendered":"proc_watch"},"content":{"rendered":"\n<pre class=\"lang:default decode:true \" ># \u672c\u4ee3\u7801\u662f\u5c06ksh\u7684\u534f\u8fdb\u7a0b\u6539\u4e3abash\u7684\u534f\u8fdb\u7a0b\u7ba1\u7406\uff0c\r\n# bash4.0\u4ee5\u540e\u652f\u6301coprocesses(\u534f\u8fdb\u7a0b)\r\n# Auth:qfongv8\r\n# Sites:selinuxplus.com\r\n#\r\n#\u4ee3\u7801\u5982\u4e0b\uff1a\r\n# REV LIST:\r\n#\r\n# set -x # Uncomment to debug this script\r\n# set -n # Uncomment to check syntax without ANY execution\r\n#\r\n####################################################\r\n########## DEFINE FILES AND VARIABLES HERE #########\r\n####################################################\r\n\r\ntypeset -u RUN_PRE_EVENT # Force to UPPERCASE\r\ntypeset -u RUN_STARTUP_EVENT # Force to UPPERCASE\r\ntypeset -u RUN_POST_EVENT # force to UPPERCASE\r\n\r\nRUN_PRE_EVENT='Y' # A 'Y' will execute, anything else will not\r\nRUN_STARTUP_EVENT='Y' # A 'Y' will execute, anything else will not\r\nRUN_POST_EVENT='Y' # A 'Y' will execute, anything else will not\r\n\r\nLOGFILE=\"\/var\/log\/svmm.log\"\r\n[[ ! -s $LOGFILE ]] &amp;amp;&amp;amp; touch $LOGFILE\r\n\r\nSCRIPT_NAME=$(basename $0)\r\n#TTY=$(tty)\r\nTTY=\"\/dev\/null\"\r\nINTERVAL=\"1\" # Seconds between sampling\r\nJOBS=\r\n\r\n####################################################\r\n############# DEFINE FUNCTIONS HERE ################\r\n####################################################\r\nusage ()\r\n{\r\necho -e \"\\n\\n\\t***** USAGE ERROR *****\"\r\necho -e \"\\n\\nUSAGE: $SCRIPT_NAME seconds process\"\r\necho -e \"\\nWill monitor the specified process for the\"\r\necho -e \"specified number of seconds.\"\r\necho -e \"\\nUSAGE: $SCRIPT_NAME [-s|-S seconds] [-m|-M minutes]\"\r\necho -e \" [-h|-H hours] [-d|-D days] [-p|-P process]\\n\"\r\necho -e \"\\nWill monitor the specified process for number of\"\r\necho -e \"seconds specified within -s seconds, -m minutes,\"\r\necho -e \"-h hours and -d days. Any combination of command\"\r\necho -e \"switches can be used.\\n\"\r\necho -e \"\\nEXAMPLE: $SCRIPT_NAME 300 dsvmm\"\r\necho -e \"\\n\\nEXAMPLE: $SCRIPT_NAME -m 5 -p dsvmm\"\r\necho -e \"\\nBoth examples will monitor the dtcalc process\"\r\necho -e \"for 5 minutes. Can specify days, hours, minutes\"\r\necho -e \"and seconds, using -d, -h, -m and -s\\n\\n\"\r\n}\r\n####################################################\r\ntrap_exit ()\r\n{\r\n# set -x # Uncommant to debug this function\r\n# Log an ending time for process monitoring\r\necho \"INTERRUPT: Program Received an Interrupt...EXITING...\" &amp;gt; $TTY\r\necho \"INTERRUPT: Program Received an Interrupt...EXITING...\" &amp;gt;&amp;gt; $LOGFILE\r\nTIMESTAMP=$(date +%D@%T) # Get a new timestamp...\r\necho -e \"MON_STOPPED: Monitoring for $PROCESS ended ==&amp;gt; $TIMESTAMP\\n\" \\\r\n&amp;gt;&amp;gt; $TTY\r\necho -e \"MON_STOPPED: Monitoring for $PROCESS ended ==&amp;gt; $TIMESTAMP\\n\" \\\r\n&amp;gt;&amp;gt; $LOGFILE\r\necho -e \"LOGFILE: All Events are Logged ==&amp;gt; $LOGFILE \\n\" &amp;gt; $TTY\r\n\r\n# Kill all functions\r\nJOBS=$(jobs -p)\r\nif [[ ! -z $JOBS &amp;amp;&amp;amp; $JOBS != '' &amp;amp;&amp;amp; $JOBS != '0' ]]\r\nthen\r\nkill $(jobs -p) 2&amp;gt;\/dev\/null 1&amp;gt;&amp;amp;2\r\nfi\r\nreturn 2\r\n}\r\n####################################################\r\npre_event_script ()\r\n{\r\n# Put anything that you want to execute BEFORE the\r\n# monitored process STARTS in this function\r\n\r\n: # No-OP - Needed as a placeholder for an empty function\r\n# Comment Out the Above colon, ':'\r\nsvmmd stop &amp;amp;&amp;amp; true\r\nsvmmd start\r\nPRE_RC=$?\r\nreturn $PRE_RC\r\n}\r\n####################################################\r\nstartup_event_script ()\r\n{\r\n# Put anything that you want to execute WHEN, or AS, the\r\n# monitored process STARTS in this function\r\n\r\n: # No-OP - Needed as a placeholder for an empty function\r\n# Comment Out the Above colon, ':'\r\n\r\nSTARTUP_RC=$?\r\nreturn $STARTUP_RC\r\n}\r\n####################################################\r\npost_event_script ()\r\n{\r\n# Put anything that you want to execute AFTER the\r\n# monitored process ENDS in this function\r\n\r\n: # No-OP - Need as a placeholder for an empty function\r\n# Comment Out the Above colon, ':'\r\n\r\nPOST_RC=$?\r\nreturn $POST_RC\r\n}\r\n####################################################\r\n# This function is used to test character strings\r\n\r\ntest_string ()\r\n{\r\nif (( $# != 1 ))\r\nthen\r\necho 'ERROR'\r\nreturn\r\nfi\r\n\r\nC_STRING=$1\r\n\r\n# Test the character string for its composition\r\n\r\ncase $C_STRING in\r\n\r\n[0-9]) echo 'POS_INT' # Integer &amp;gt;= 0\r\n;;\r\n[-0-9]) echo 'NEG_INT' # Integer &amp;lt; 0 ;; [a-z]) echo 'LOW_CASE' # lower case text ;; [A-Z]) echo 'UP_CASE' # UPPER case text ;; [a-z]|[A-Z]) echo 'MIX_CASE' # MIxed CAse text ;; *) echo 'UNKNOWN' # Anything else ;; esac } #################################################### proc_watch () { # set -x # Uncomment to debug this function # This function does all of the process monitoring! while : # Loop Forever!! do case $RUN in 'Y') # This will run the startup_event_script, which is a function if [[ $RUN_STARTUP_EVENT = 'Y' ]] then echo \"STARTUP EVENT: Executing Startup Event Script...\"\\ &amp;gt; $TTY\r\necho \"STARTUP EVENT: Executing Startup Event Script...\"\\\r\n&amp;gt;&amp;gt; $LOGFILE\r\n\r\nstartup_event_script # USER DEFINED FUNCTION!!!\r\nRC=$? # Check the Return Code!!\r\nif (( \"RC\" == 0 ))\r\nthen\r\necho \"SUCCESS: Startup Event Script Completed RC - \\\r\n${RC}\" &amp;gt; $TTY\r\necho \"SUCCESS: Startup Event Script Completed RC - \\\r\n${RC}\" &amp;gt;&amp;gt; $LOGFILE\r\n\r\nelse\r\necho \"FAILURE: Startup Event Script FAILED RC - \\\r\n${RC}\" &amp;gt; $TTY\r\necho \"FAILURE: Startup Event Script FAILED RC - \\\r\n${RC}\" &amp;gt;&amp;gt; $LOGFILE\r\nfi\r\nfi\r\ndeclare -i PROC_COUNT='-1' # Reset the Counters\r\ndeclare -i LAST_COUNT='-1'\r\n# Loop until the process(es) end(s)\r\n\r\nuntil (( \"PROC_COUNT\" == 0 ))\r\ndo\r\n\r\n# This function is a Co-Process. $BREAK checks to see if\r\n# \"Program Interrupt\" has taken place. If so BREAK will\r\n# be 'Y' and we exit both the loop and function.\r\n\r\nPROC_COUNT=$(ps aux | grep -v \"grep $PROCESS\" \\\r\n| grep -v $SCRIPT_NAME \\\r\n| grep $PROCESS | wc -l) &amp;gt;\/dev\/null 2&amp;gt;&amp;amp;1\r\n#echo $PROC_COUNT &amp;gt; $TTY\r\nif (( \"LAST_COUNT\" &amp;gt; 0 &amp;amp;&amp;amp; \"LAST_COUNT\" != \"PROC_COUNT\" ))\r\nthen\r\n# The Process Count has Changed...\r\nTIMESTAMP=$(date +%D@%T)\r\n# Get a list of the PID of all of the processes\r\nPID_LIST=$(ps aux | grep -v \"grep $PROCESS\" \\\r\n| grep -v $SCRIPT_NAME \\\r\n| grep $PROCESS | awk '{print $2}')\r\n\r\necho \"PROCESS COUNT: $PROC_COUNT $PROCESS\\\r\nProcesses Running ==&amp;gt; $TIMESTAMP\" &amp;gt;&amp;gt; $LOGFILE &amp;amp;\r\necho \"PROCESS COUNT: $PROC_COUNT $PROCESS\\\r\nProcesses Running ==&amp;gt; $TIMESTAMP\" &amp;gt; $TTY\r\necho ACTIVE PIDS: $PID_LIST &amp;gt;&amp;gt; $LOGFILE &amp;amp;\r\necho ACTIVE PIDS: $PID_LIST &amp;gt; $TTY\r\nfi\r\nLAST_COUNT=$PROC_COUNT\r\nsleep $INTERVAL # Needed to reduce CPU load!\r\ndone\r\n\r\nRUN='N' # Turn the RUN Flag Off\r\nTIMESTAMP=$(date +%D@%T)\r\necho \"ENDING PROCESS: $PROCESS END time ==&amp;gt;\\\r\n$TIMESTAMP\" &amp;gt;&amp;gt; $LOGFILE &amp;amp;\r\necho \"ENDING PROCESS: $PROCESS END time ==&amp;gt;\\\r\n$TIMESTAMP\" &amp;gt; $TTY\r\n\r\n# This will run the post_event_script, which is a function\r\n\r\nif [[ $RUN_POST_EVENT = 'Y' ]]\r\nthen\r\necho \"POST EVENT: Executing Post Event Script...\"\\\r\n&amp;gt; $TTY\r\necho \"POST EVENT: Executing Post Event Script...\"\\\r\n&amp;gt;&amp;gt; $LOGFILE &amp;amp;\r\n\r\npost_event_script # USER DEFINED FUNCTION!!!\r\ndeclare -i RC=$?\r\nif (( \"RC\" == 0 ))\r\nthen\r\necho \"SUCCESS: Post Event Script Completed RC - \\\r\n${RC}\" &amp;gt; $TTY\r\necho \"SUCCESS: Post Event Script Completed RC - \\\r\n${RC}\" &amp;gt;&amp;gt; $LOGFILE\r\nelse\r\necho \"FAILURE: Post Event Script FAILED RC - ${RC}\"\\\r\n&amp;gt; $TTY\r\necho \"FAILURE: Post Event Script FAILED RC - ${RC}\"\\\r\n&amp;gt;&amp;gt; $LOGFILE\r\nfi\r\nfi\r\n;;\r\n\r\n'N')\r\n\r\n# This will run the pre_event_script, which is a function\r\n\r\nif [[ $RUN_PRE_EVENT = 'Y' ]]\r\nthen\r\necho \"PRE EVENT: Executing Pre Event Script...\" &amp;gt; $TTY\r\necho \"PRE EVENT: Executing Pre Event Script...\" &amp;gt;&amp;gt; $LOGFILE\r\n\r\npre_event_script # USER DEFINED FUNCTION!!!\r\nRC=$? # Check the Return Code!!!\r\nif (( \"RC\" == 0 ))\r\nthen\r\necho \"SUCCESS: Pre Event Script Completed RC - ${RC}\"\\\r\n&amp;gt; $TTY\r\necho \"SUCCESS: Pre Event Script Completed RC - ${RC}\"\\\r\n&amp;gt;&amp;gt; $LOGFILE\r\nelse\r\necho \"FAILURE: Pre Event Script FAILED RC - ${RC}\"\\\r\n&amp;gt; $TTY\r\necho \"FAILURE: Pre Event Script FAILED RC - ${RC}\"\\\r\n&amp;gt;&amp;gt; $LOGFILE\r\nfi\r\nfi\r\n\r\necho \"WAITING: Waiting for $PROCESS to \\\r\nstartup...Monitoring...\" &amp;gt;$TTY\r\n\r\ndeclare -i PROC_COUNT='-1' # Initialize to a fake value\r\n# echo $PROC_COUNT &amp;gt;$TTY\r\n# Loop until at least one process starts\r\n\r\nuntil (( \"PROC_COUNT\" &amp;gt; 0 ))\r\ndo\r\n\r\n# This is a Co-Process. This checks to see if a \"Program\r\n# Interrupt\" has taken place. If so BREAK will be 'Y' and\r\n# we exit both the loop and function\r\n\r\nPROC_COUNT=$(ps aux | grep -v \"grep $PROCESS\" \\\r\n| grep -v $SCRIPT_NAME | grep $PROCESS | wc -l) \\\r\n&amp;gt;\/dev\/null 2&amp;gt;&amp;amp;1\r\n\r\n# echo $PROC_COUNT &amp;gt; $TTY\r\nsleep $INTERVAL # Needed to reduce CPU load!\r\ndone\r\n\r\nRUN='Y' # Turn the RUN Flag On\r\n\r\nTIMESTAMP=$(date +%D@%T)\r\n\r\nPID_LIST=$(ps aux | grep -v \"grep $PROCESS\" \\\r\n| grep -v $SCRIPT_NAME \\\r\n| grep $PROCESS | awk '{print $2}')\r\n\r\nif (( \"PROC_COUNT\" == 1 ))\r\nthen\r\n# echo test************************** &amp;gt;$TTY\r\necho \"START PROCESS: $PROCESS START time ==&amp;gt;\\\r\n$TIMESTAMP\" &amp;gt;&amp;gt; $LOGFILE &amp;amp;\r\necho ACTIVE PIDS: $PID_LIST &amp;gt;&amp;gt; $LOGFILE &amp;amp;\r\necho \"START PROCESS: $PROCESS START time ==&amp;gt;\\\r\n$TIMESTAMP\" &amp;gt; $TTY\r\necho ACTIVE PIDS: $PID_LIST &amp;gt; $TTY\r\nelif (( \"PROC_COUNT\" &amp;gt; 1 ))\r\nthen\r\necho \"START PROCESS: $PROC_COUNT $PROCESS\\\r\nProcesses Started: START time ==&amp;gt; $TIMESTAMP\" &amp;gt;&amp;gt; $LOGFILE &amp;amp;\r\necho ACTIVE PIDS: $PID_LIST &amp;gt;&amp;gt; $LOGFILE &amp;amp;\r\necho \"START PROCESS: $PROC_COUNT $PROCESS\\\r\nProcesses Started: START time ==&amp;gt; $TIMESTAMP\" &amp;gt; $TTY\r\necho ACTIVE PIDS: $PID_LIST &amp;gt; $TTY\r\nfi\r\n;;\r\nesac\r\ndone\r\n}\r\n\r\n####################################################\r\n############## START OF MAIN #######################\r\n####################################################\r\n\r\n### SET A TRAP ####\r\n\r\ntrap 'kill -9 $COPROC_PID 2&amp;gt;\/dev\/null;trap_exit \\\r\n2&amp;gt;\/dev\/null;exit 0' 1 2 3 15\r\n\r\nBREAK='N' # The BREAK variable is used in the co-process proc_watch\r\nPROCESS= # Initialize to null\r\ndeclare -i TOTAL_SECONDS=0\r\n#print -p $BREAK\r\n# Check commnand line arguments\r\n\r\nif (( $# &amp;gt; 10 || $# &amp;lt; 2 )) then usage exit 1 fi # Check to see if only the seconds and a process are # the only arguments if [[ ($# -eq 2) &amp;amp;&amp;amp; ($1 != -*) &amp;amp;&amp;amp; ($2 != -*) ]] then NUM_TEST=$(test_string $1) # Is this an Integer? if [[ \"$NUM_TEST\" = 'POS_INT' ]] then TOTAL_SECONDS=$1 # Yep - It.s an Integer PROCESS=$2 # Can be anything else usage exit 1 fi else # Since getopts does not care what arguments it gets, let.s # do a quick sanity check to make sure that we only have # between 2 and 10 arguments and the first one must start # with a -* (hyphen and anything), else usage error case \"$#\" in [2-10]) if [[ $1 != -* ]]; then usage; exit 1 fi ;; esac HOURS=0 # Initialize all to zero MINUTES=0 SECS=0 DAYS=0 # Use getopts to parse the command line arguments # For each $OPTARG for DAYS, HOURS, MINUTES and DAYS check to see # that each one is an integer by using the check_string function while getopts \":h:H:m:M:s:S:d:D:P:p:\" OPT_LIST 2&amp;gt;\/dev\/null\r\ndo\r\ncase $OPT_LIST in\r\nh|H) [[ $(test_string $OPTARG) != 'POS_INT' ]] &amp;amp;&amp;amp; usage &amp;amp;&amp;amp; exit 1\r\n(( HOURS = $OPTARG * 3600 )) # 3600 seconds per hour\r\n;;\r\nm|H) [[ $(test_string $OPTARG) != 'POS_INT' ]] &amp;amp;&amp;amp; usage &amp;amp;&amp;amp; exit 1\r\n(( MINUTES = $OPTARG * 60 )) # 60 seconds per minute\r\n;;\r\ns|S) [[ $(test_string $OPTARG) != 'POS_INT' ]] &amp;amp;&amp;amp; usage &amp;amp;&amp;amp; exit 1\r\nSECS=\"$OPTARG\" # seconds are seconds\r\n;;\r\nd|D) [[ $(test_string $OPTARG) != 'POS_INT' ]] &amp;amp;&amp;amp; usage &amp;amp;&amp;amp; exit 1\r\n(( DAYS = $OPTARG * 86400 )) # 86400 seconds per day\r\n;;\r\np|P) PROCESS=$OPTARG # process can be anything\r\n;;\r\n\\?) usage # USAGE ERROR\r\nexit 1\r\n;;\r\n:) usage\r\nexit 1\r\n;;\r\n*) usage\r\nexit 1\r\n;;\r\nesac\r\ndone\r\nfi\r\n\r\n# We need to make sure that we have a process that\r\n# is NOT null or empty! - sanity check - The double quotes are required!\r\n\r\nif [[ -z \"$PROCESS\" || \"$PROCESS\" = '' ]]\r\nthen\r\nusage\r\nexit 1\r\nfi\r\n\r\n# Check to see that TOTAL_SECONDS was not previously set\r\n\r\nif (( TOTAL_SECONDS == 0 ))\r\nthen\r\n# Add everything together if anything is &amp;gt; 0\r\nif [[ $SECS -gt 0 || $MINUTES -gt 0 || $HOURS -gt 0 \\\r\n|| $DAYS -gt 0 ]]\r\nthen\r\n(( TOTAL_SECONDS = SECS + MINUTES + HOURS + DAYS ))\r\nfi\r\nfi\r\n\r\n# Last Sanity Check!\r\n\r\nif (( TOTAL_SECONDS $TTY\r\nps aux | grep -v \"grep $PROCESS\" | grep -v $SCRIPT_NAME \\\r\n| grep $PROCESS &amp;gt; $TTY\r\n\r\nPROC_RC=$? # Get the initial state of the monitored function\r\necho $PROC_RC\r\necho &amp;gt;$TTY # Send a blank line to the screen\r\n\r\n(( PROC_RC != 0 )) &amp;amp;&amp;amp; echo -e \"\\nThere are no $PROCESS processes running\\n\"\r\n\r\nif (( PROC_RC == 0 )) # The Target Process(es) is\/are running...\r\nthen\r\nRUN='Y' # Set the RUN flag to true, or yes.\r\n\r\ndeclare -i PROC_COUNT # Strips out the \"padding\" for display\r\n\r\nPROC_COUNT=$(ps aux | grep -v \"grep $PROCESS\" | grep -v \\\r\n$SCRIPT_NAME | grep $PROCESS | wc -l) &amp;gt;\/dev\/null 2&amp;gt;&amp;amp;1\r\nif (( PROC_COUNT == 1 ))\r\nthen\r\necho -e \"The $PROCESS process is currently\\\r\nrunning...Monitoring... \\n\"\r\nelif (( PROC_COUNT &amp;gt; 1 ))\r\nthen\r\nprint \"There are $PROC_COUNT $PROCESS processes currently\\\r\nrunning...Monitoring...\\n\"\r\nfi\r\nelse\r\necho \"The $PROCESS process is not currently running...monitoring...\"\r\nRUN='N' # Set the RUN flag to false, or no.\r\nfi\r\n\r\nTIMESTAMP=$(date +%D@%T) # Time that this script started monitoring\r\n\r\n# Get a list of the currently active process IDs\r\n\r\nPID_LIST=$(ps aux | grep -v \"grep $PROCESS\" \\\r\n| grep -v $SCRIPT_NAME \\\r\n| grep $PROCESS | awk '{print $2}')\r\n\r\necho \"MON_STARTED: Monitoring for $PROCESS began ==&amp;gt; $TIMESTAMP\" \\\r\n| tee -a $LOGFILE\r\necho ACTIVE PIDS: $PID_LIST | tee -a $LOGFILE\r\n#echo test*****\r\n\r\n##### NOTICE ####\r\n# We kick off the \"proc_watch\" function below as a \"Co-Process\"\r\n# This sets up a two way communications link between the\r\n# \"proc_watch\" background function and this \"MAIN BODY\" of\r\n# the script. This is needed because the function has two\r\n# \"infinite loops\", with one always executing at any given time.\r\n# Therefore we need a way to break out of the loop in case of\r\n# an interrupt, i.e. CTRL+C, and when the countdown is complete.\r\n# The \"pipe appersand\", |&amp;amp;, creates the background Co-Process\r\n# and we use \"print -p $VARIABLE\" to transfer the variable.s\r\n# value back to the background co-process.\r\n###################################\r\n\r\n&lt;strong&gt;&lt;span style=\"color: #ff0000;\"&gt;coproc proc_watch # Create a Background Co-Process!!&lt;\/span&gt;&lt;\/strong&gt;\r\n&lt;strong&gt;&lt;span style=\"color: #ff0000;\"&gt; WATCH_PID=$! # Get the process ID of the last background job!&lt;\/span&gt;&lt;\/strong&gt;\r\n\r\n#echo \"test over \"\r\n# Start the Count Down!\r\n#echo $BREAK\r\ndeclare -i SECONDS_LEFT=$TOTAL_SECONDS\r\necho $SECONDS_LEFT\r\nwhile (( SECONDS_LEFT &amp;gt; 0 ))\r\ndo\r\n# Next send the current value of $BREAK to the Co-Process\r\n# proc_watch, which was piped to the background...\r\n\r\nprint -p $BREAK 2&amp;gt;\/dev\/null\r\n(( SECONDS_LEFT = SECONDS_LEFT - 1 ))\r\nsleep 1 # 1 Second Between Counts\r\ndone\r\n\r\n# Finished - Normal Timeout Exit...\r\nTIMESTAMP=$(date +%D@%T) # Get a new timestamp...\r\necho -e \"MON_STOPPED: Monitoring for $PROCESS ended ==&amp;gt; $TIMESTAMP\\n\" \\\r\n| tee -a $LOGFILE\r\n\r\necho -e \"LOGFILE: All Events are Logged ==&amp;gt; $LOGFILE \\n\"\r\n\r\n# Tell the proc_watch function to break out of the loop and die\r\n\r\nkill -9 $COPROC_PID&amp;gt;\/dev\/null\r\nBREAK='Y'\r\nprint -p $BREAK 2&amp;gt;\/dev\/null\r\nexit 0\r\n\r\n# End of Script<\/pre>\n","protected":false},"excerpt":{"rendered":"<p># \u672c\u4ee3\u7801\u662f\u5c06ksh\u7684\u534f\u8fdb\u7a0b\u6539\u4e3abash\u7684\u534f\u8fdb\u7a0b\u7ba1&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[17,19,18],"_links":{"self":[{"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/posts\/165"}],"collection":[{"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=165"}],"version-history":[{"count":2,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/posts\/165\/revisions"}],"predecessor-version":[{"id":241,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=\/wp\/v2\/posts\/165\/revisions\/241"}],"wp:attachment":[{"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=165"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=165"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.selinuxplus.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=165"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}