Managing Client Log File Size for the UNIX and Linux Configuration Manager Clients
Details about the log files created by the UNIX and Linux Clients for System Center 2012 R2 Configuration Manager can be found in this article. The UNIX and Linux clients do not rotate or manage the size of the client log files. Where possible, such as on Linux systems, it is recommended to use system tools such as logrotate to manage the Configuration Manager client log files. However, logrotate is not available on all operating systems supported by the Client. For cases where logrotate is not available, the following example script can be distributed and scheduled to rotate Configuration Manager Client log files. This example script is viable for all UNIX and Linux operating systems supported by the Configuration Manager Client.
Deploying the script
Configuration Manager's software distribution is an ideal mechanism to deploy the script to managed UNIX or Linux clients. To deploy the script with software distribution, create a package with the script contained in the package's source directory, and use a command such as: /bin/sh -c "cp logrotate.sh /opt/microsoft/configmgr/bin/" as the program. This command would copy the file named logrotate.sh to the default bin directory for the client.
Scheduling the script
The cron daemon is a good mechanism for regular scheduling of the log rotation script. A cron job can be scheduled daily, weekly, or monthly to rotate the Configuration Manager clients and retain a specified number of archived logs to keep. If software distribution is used to deploy the script to the clients, a crontab file can also be distributed with the script or the package can invoke a script or command to edit the active crontab file.
Example Log Rotation Script
#!/bin/sh
# This file is expected to be placed in CM's bin directory, and run from that directory since this script uses relative paths.
# Usage:
# logrotate NUMBER_OF_LOGS_TO_KEEP
# where NUMBER_OF_LOGS_TO_KEEP is a postive integer
CM_DIR=..
OMI_DIR=../../omi
OMI_LOGDIR=$OMI_DIR/var/log
if [ -x /usr/xpg4/bin/awk ]; then
AWK=/usr/xpg4/bin/awk
else
AWK=awk
fi
CCM_IS_RUNNING=0
OMI_IS_RUNNING=0
if [ -f "$CM_DIR/CCMExec.pid" ]; then
pid=`cat $CM_DIR/CCMExec.pid`
ps -aef | $AWK -v OFS=',' '{ print $2,$8 }' | grep "^$pid" | grep "ccmexec" 1> /dev/null
if [ $? -eq 0 ]; then
CCM_IS_RUNNING=1
fi
fi
if [ -f "$OMI_DIR/var/run/omiserver.pid" ]; then
pid=`cat $OMI_DIR/var/run/omiserver.pid`
ps -aef | $AWK -v OFS=',' '{ print $2,$8 }' | grep "^$pid" | grep "omiserver" 1> /dev/null
if [ $? -eq 0 ]; then
OMI_IS_RUNNING=1
fi
fi
# This will extract the CM logging path for scxcm.log, which can be set on install time to be something user specified.
# It reads in the scxcm.conf file in the CM installation's etc directory, and greps for PATH, which will be the path of any log file.
# A user may configure multiple log paths for different logging levels, but we only take the first log path in this implementation.
CM_LOGPATHS=`cat ../etc/scxcm.conf | grep PATH`
i=0
for temp in $CM_LOGPATHS; do
if [ $i -eq 1 ]; then
CM_LOGDIR=`dirname $temp`
break
fi
i=`expr $i + 1`
done
if [ -z "$CM_LOGDIR" ]; then
echo "ERROR: Unable to determine CM's logging directory"
exit 1
fi
PLATFORM=`uname -s`
case $PLATFORM in
Linux)
ZIP="gz"
COMPRESS="gzip"
;;
HP-UX)
ZIP="Z"
COMPRESS="compress -f"
;;
AIX)
ZIP="Z"
COMPRESS="compress -f"
;;
SunOS)
ZIP="Z"
COMPRESS="compress -f"
;;
*)
echo "Unknown platform"
exit 1
;;
esac
wait_for_omi_to_stop()
{
if [ -f "$OMI_DIR/var/run/omiserver.pid" ]; then
pid=`cat $OMI_DIR/var/run/omiserver.pid`
if [ -z "$pid" ]; then
echo "Cannot get pid for omiserver process; process may still exist. Please manually restart omiserver."
else
# wait for it to exit
stop=0
count=5
while [ $stop -eq 0 ]; do
count=`expr $count - 1`
# Check to see if omiserver is still running.
ps -aef | $AWK -v OFS=',' '{ print $2,$8 }' | grep "^$pid" | grep "omiserver" 1> /dev/null
if [ $? -ne 0 ]; then
stop=1
elif [ $count -eq 0 ]; then
stop=1
if [ $? -eq 0 ]; then # pid matches commandline..
echo "OMI Server process did not exit properly, forcing it to exit."
kill -9 "$pid"
fi
else
echo "Waiting for omiserver to exit..."
sleep 1
fi
done
fi
fi
}
service_action_delay()
{
COUNT=0
while [ $COUNT -lt 15 ]; do
/usr/bin/svcs -H $1 2> /dev/null | grep -i $2 2> /dev/null 1> /dev/null
[ $? -eq 0 ] && break
echo "Waiting for service: $1 ..."
sleep 2
COUNT=`expr $COUNT + 1`
done
}
pre_omi_and_ccmexec()
{
if [ $OMI_IS_RUNNING -eq 1 ]; then
case $PLATFORM in
Linux|HP-UX|AIX)
../../omi/bin/omiserver -s
wait_for_omi_to_stop
;;
SunOS)
version=`uname -r`
if [ "$version" = "5.9" ]; then
if [ $CCM_IS_RUNNING -eq 1 ]; then
./ccmexec --openlogfile
fi
../../omi/bin/omiserver -s
wait_for_omi_to_stop
else
if [ $CCM_IS_RUNNING -eq 1 ]; then
svcadm disable -s svc:/application/management/ccmexecd 2> /dev/null
fi
svcadm disable -s svc:/application/management/omiserver 2> /dev/null
# wait for omiserver to stop (ccmexecd will enter disabled mode first because of the dependency)
service_action_delay svc:/application/management/omiserverd disabled
fi
;;
esac
fi
}
post_omi_and_ccmexec()
{
if [ $OMI_IS_RUNNING -eq 1 ]; then
case $PLATFORM in
Linux|HP-UX|AIX)
../../omi/bin/omiserver -d 2> /dev/null 1> /dev/null
if [ $CCM_IS_RUNNING -eq 1 ]; then
./ccmexec --openlogfile
fi
;;
SunOS)
version=`uname -r`
if [ "$version" = "5.9" ]; then
../../omi/bin/omiserver -d 2> /dev/null 1> /dev/null
if [ $CCM_IS_RUNNING -eq 1 ]; then
./ccmexec --openlogfile
fi
else
svcadm enable -s svc:/application/management/omiserver 2> /dev/null
if [ $CCM_IS_RUNNING -eq 1 ]; then
svcadm enable -s svc:/application/management/ccmexecd 2> /dev/null
fi
fi
;;
esac
fi
}
usage()
{
echo "Usage:"
echo " logrotate NUMBER_OF_LOGS_TO_KEEP"
echo " where NUMBER_OF_LOGS_TO_KEEP is a postive integer"
exit 1
}
if [ -z "$1" ]; then
usage
fi
logs_to_keep=$1
if [ $logs_to_keep -le 0 ]; then
usage
fi
# expects $1 - log path
# expects $2 - log name
rotate_log()
{
LOGPATH=$1
LOG_NAME=$2
log_archives=`ls -t $LOGPATH/$LOG_NAME.* 2> /dev/null`
# move the sorted list $log_archives into $1, $2, $3, etc..
set -- split $log_archives
shift
num_files_found=$#
out_path=
if [ $logs_to_keep -gt $num_files_found ]; then
# find lowest number that doesn't exist from 1 to $logs_to_keep
i=1
while [ $i -le $logs_to_keep ]; do
value=`ls $LOGPATH/$LOG_NAME.$i.$ZIP 2> /dev/null`
if [ $? -ne 0 ]; then
out_path="$LOGPATH/$LOG_NAME.$i.$ZIP"
break
fi
i=`expr $i + 1`
done
else
if [ $logs_to_keep -lt $num_files_found ]; then
# Note: should likely use a full path here to ensure nothing bad happens.
num_logs_to_delete=`expr $num_files_found - $logs_to_keep`
last_good_log_name=
i=1
for log in $log_archives; do
if [ $i -gt $logs_to_keep ]; then
rm $log
else
last_good_log_name=$log
fi
i=`expr $i + 1`
done
else
for log in $log_archives; do
last_good_log_name=$log
done
fi
out_path=$last_good_log_name
fi
out_path=`echo $out_path | sed "s/.$ZIP//"`
echo "Rotating log to $out_path.$ZIP"
if [ ! -f "$LOGPATH/$LOG_NAME" ]; then
touch $LOGPATH/$LOG_NAME
fi
mv $LOGPATH/$LOG_NAME $out_path
rm -f $out_path.$ZIP
$COMPRESS $out_path
touch $LOGPATH/$LOG_NAME
}
# stop ccmexec
pre_omi_and_ccmexec
rotate_log $CM_LOGDIR scxcm.log
rotate_log $OMI_LOGDIR omiserver.log
rotate_log $OMI_LOGDIR omiagent.root.root.log
# start ccmexec
post_omi_and_ccmexec