blob: 4ec25f481e4669c0a37980c1860352b98a0596c0 [file] [log] [blame]
#!/bin/sh
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This script should be called daily to clean up log files.
# It can also be called with "--no-periodic" directly from an init
# script in which case it will clean up but not rotate.
. /usr/share/cros/disk_utils.sh
CLEANUP_PAUSED_FILE="/var/lib/cleanup_logs_paused"
NUM_DAYS_TO_PRESERVE=7
MAX_SUBDIR_SIZE=100 # MB
MAX_SUBDIR_FILES=21
# Threshold for additional histogram reporting (in 1KB blocks), 1GB in total.
ADDITIONAL_REPORTING_THRESHOLD_BLOCKS=1048576
SHADOW="/home/.shadow"
ENCRYPTED_REBOOT_VAULT="/mnt/stateful_partition/reboot_vault"
# Paths for the CRX cache. Shared with installer/crx-import.conf
UNVALIDATED_CRX_CACHE="${STATEFUL}/unencrypted/import_extensions"
VALIDATED_CRX_CACHE=/var/cache/external_cache
report_additional_statistics() {
# Number of users on device.
local user_count
user_count="$(find "${SHADOW}" -maxdepth 1 -mindepth 1 -type d | wc -l)"
metrics_client -s Platform.DiskUsage.UsersOnDevice "${user_count}"
}
# Remove older files, keep deleting until the directory is less than 100MB
# or only one day old files remains. ...and also delete older files if
# there are too many.
remove_old_files() {
local subdir="$1"
local file_pattern="$2"
local mtime="${NUM_DAYS_TO_PRESERVE}"
if [ ! -d "${subdir}" ]; then
return
fi
while [ "${mtime}" -ge 1 ]; do
find "${subdir}" -type f -name "${file_pattern}" -mtime "+${mtime}" -delete
if [ "$(du -s --block-size=1M "${subdir}" | cut -f 1)" -gt \
"${MAX_SUBDIR_SIZE}" ]; then
: "$(( mtime -= 1 ))"
else
break
fi
done
# Delete all but the most recent MAX_SUBDIR_FILES files.
#
# Note that 'ls -t' doesn't have a "null terminated" mode apparently
# because you're not supposed to use it for scripts, so we end up
# using several steps.
find "${subdir}" -type f -name "${file_pattern}" -printf "%T+ %p\0" | \
sort -zr | \
cut -z -d ' ' -f 2- | \
tail -z "-n+$(( MAX_SUBDIR_FILES + 1 ))" | \
xargs -r -0 rm
}
rotate_file() {
local file="$1"
if [ ! -f "${file}" ]; then
# Avoid creating an empty file if it does not exist to begin with
return
fi
if [ ! -s "${file}" ]; then
# Avoid creating an empty file if it's already empty.
return
fi
local basename="${file%%.*}"
local extension="${file#*.}"
if [ "${basename}" = "${extension}" ]; then
extension=""
else
extension=".${extension}"
fi
echo Rotating "${file}"
for i in $(seq "${NUM_DAYS_TO_PRESERVE}" -1 2); do
mv -f "${basename}.$((i - 1))${extension}" "${basename}.$i${extension}"
done
mv -f "${basename}${extension}" "${basename}.1${extension}"
touch "${basename}${extension}"
chmod --reference="${basename}.1${extension}" "${basename}${extension}"
chown --reference="${basename}.1${extension}" "${basename}${extension}"
}
rotate_logs() {
echo Rotating rsyslogd logs
for x in messages secure net.log faillog session_manager atrus.log \
tlsdate.log authpolicy.log tpm-firmware-updater.log arc.log \
recover_duts/recover_duts.log hammerd.log upstart.log; do
rotate_file "/var/log/${x}"
done
pkill -HUP rsyslogd
}
# Wipe the unencyrpted CRX cache if it still exists.
wipe_crx_cache() {
local root_dev
local removable
local disk_percent
# If we are on removable media or we haven't imported the crx cache,
# don't wipe.
root_dev="$(basename "$(rootdev -s -d)")"
removable="$(cat "/sys/block/${root_dev}/removable")" || :
disk_percent="$(get_stateful_usage_percent)" || :
[ -z "${disk_percent}" ] && disk_percent=0
if [ "${removable:-0}" -eq 0 ] && [ -d "${UNVALIDATED_CRX_CACHE}" ] && \
[ -f "${VALIDATED_CRX_CACHE}/.initialized" ] && \
[ "${disk_percent}" -gt 25 ]; then
echo "Wiping unvalidated crx cache as it has already been imported."
rm -rf "${UNVALIDATED_CRX_CACHE}"
fi
}
remove_old_files_encrypted_reboot_vault() {
find "${ENCRYPTED_REBOOT_VAULT}" -type f -mtime "+${NUM_DAYS_TO_PRESERVE}" \
-delete
}
remove_old_pattern_log_files() {
# Remove old biometrics cypto init, daemon, and firmware
# updater logs
remove_old_files /var/log/bio_crypto_init "*"
remove_old_files /var/log/biod "biod.*"
remove_old_files /var/log/biod "bio_fw_updater.*"
# Remove old chrome logs (not logged in)
remove_old_files /var/log/chrome "chrome_*-*"
# Remove old chrome logs (logged in)
remove_old_files /home/chronos/user/log "chrome_*-*"
# Remove old miscellaneous UI logs
remove_old_files /var/log/ui "ui.*-*"
# Remove old update engine logs
remove_old_files /var/log/update_engine "update_engine.*-*"
# Remove old power manager logs
remove_old_files /var/log/power_manager "power*"
# Remove old vmlog logs (written by metrics_daemon)
remove_old_files /var/log/vmlog "vmlog.*"
# Remove old modemfwd helper logs
remove_old_files /var/log/modemfwd "helper_log.*"
}
usage() {
echo "usage: $0 [--no-periodic]"
echo
echo "Delete old logs and perform periodic tasks like rotating logs."
echo
echo "This program always deletes old log files for programs that"
echo "create one log per boot. Unless called with --no-periodic"
echo "it will also do periodic tasks like rotating log files"
echo "and sending metrics."
}
main() {
if [ "$#" -eq 1 ] && [ "$1" != "--no-periodic" ] ||
[ "$#" -gt 1 ]; then
usage
return 1
fi
if [ -r "${CLEANUP_PAUSED_FILE}" ]; then
echo "Exiting early because ${CLEANUP_PAUSED_FILE} exists."
return 0
fi
remove_old_pattern_log_files
# Remove iwlwifi logs older than one hour, since they are large.
find /var/log -name "last_iwlwifi_dump*" -mmin +60 -delete
# Remove old files in the encrypted reboot vault.
remove_old_files_encrypted_reboot_vault
# Quit if called at init; everything below only happens periodically
if [ "$1" = "--no-periodic" ]; then
return 0
fi
# Rotate other logs
rotate_logs
# Report disk usage statistics
METRICS_ARGS="0 1073741824 50"
metrics_client Platform.DiskUsageVar \
"$(du -sxk /var/ | awk '{print $1}')" ${METRICS_ARGS}
metrics_client Platform.DiskUsageChronos \
"$(du -sxk /home/chronos | awk '{print $1}')" ${METRICS_ARGS}
# Report overall stateful usage.
metrics_client -e Platform.StatefulUsage "$(get_stateful_usage_percent)" 101
# Report lifetime writes from the stateful partition in GiBs.
LIFETIME_WRITES="$(get_stateful_lifetime_writes)"
metrics_client Platform.StatefulLifetimeWrites \
"$((LIFETIME_WRITES / 1048576))" 0 16777216 100
# Report used space from the stateful partition in GBs.
STATEFUL_USED="$(get_stateful_used_space_blocks 1000)"
metrics_client Platform.StatefulUsedSpace \
"$((STATEFUL_USED / 1000000))" 0 16777216 50
# Report free space from the stateful partition in MBs. Some boards
# ship with a variety of SSD sizes, so free space metrics can be
# useful in addition to used space. Record in MB so we have higher
# precision in the buckets close to zero (out of space). Max out at
# 2 TB.
STATEFUL_FREE="$(get_stateful_free_space_blocks 1000)"
metrics_client Platform.StatefulFreeSpace \
"$((STATEFUL_FREE / 1000))" 0 2097152 50
NUMBER_OF_USERS="$(ls /home/user/ | wc -l)"
metrics_client Platform.DiskUsage.NumUserHomeDirectories \
"${NUMBER_OF_USERS}" 1 50 50
local last_activity
if ! last_activity="$(cryptohome --action=dump_last_activity)" ; then
logger -t "chromeos-cleanup-logs" -p warning \
"cryptohome dump_last_activity failed!"
metrics_client -s Login.UsersActiveWeekly.Percent 0
else
USERS_ACTIVE_DAILY="$(echo "${last_activity}" |
awk 'BEGIN {count = 0} $2 <= 1 {++count} END {print count}')"
metrics_client -s Login.UsersActiveDaily "${USERS_ACTIVE_DAILY}"
USERS_ACTIVE_WEEKLY="$(echo "${last_activity}" |
awk 'BEGIN {count = 0} $2 <= 7 {++count} END {print count}')"
metrics_client -s Login.UsersActiveWeekly "${USERS_ACTIVE_WEEKLY}"
USERS_ACTIVE_28DAYS="$(echo "${last_activity}" |
awk 'BEGIN {count = 0} $2 <= 28 {++count} END {print count}')"
metrics_client -s Login.UsersActive28Days "${USERS_ACTIVE_28DAYS}"
if [ "${NUMBER_OF_USERS}" -gt 0 ] ; then
metrics_client -s Login.UsersActiveWeekly.Percent \
"$((WEEKLY_USERS_ACTIVE * 100 / NUMBER_OF_USERS))"
else
# Note that this metric is also reported if dump_last_activity failed.
# See above.
metrics_client -s Login.UsersActiveWeekly.Percent 0
fi
# Report days since the least frequently used account signed in.
# It is reported every time to measure effect of autodeletion feature.
DAYS_SINCE_LFU_ACCOUNT_SIGNIN="$(echo "${last_activity}" |
awk 'BEGIN {max = 0} $2 > max {max = $2} END {print max}')"
# Check if there are any users.
if [ "${DAYS_SINCE_LFU_ACCOUNT_SIGNIN}" != "" ]; then
metrics_client Login.LeastUsedAccountDays \
"${DAYS_SINCE_LFU_ACCOUNT_SIGNIN}" 1 90 90
fi
fi
# Report additional metrics if we are low on free space.
if [ "$(get_stateful_free_space_blocks)" -le \
"${ADDITIONAL_REPORTING_THRESHOLD_BLOCKS}" ] ; then
report_additional_statistics
fi
wipe_crx_cache
}
main "$@"