-
Notifications
You must be signed in to change notification settings - Fork 14
/
sysprep-op-logfiles.sh
209 lines (186 loc) · 7.7 KB
/
sysprep-op-logfiles.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/usr/bin/env bash
#
# Remove log files from the guest
#
# Basic outline for treatment of log directories:
# 1. Section 1 of 'log directories' loop:
# Create a tmpfs file system and copy any existing files from the log
# directory to the new file system
# 2. Section 2 of 'log directories' loop:
# Mount the tmpfs file system over the top of the existing on-disk log
# files directory. This *hopefully* means than any process relying on
# files in the log directory will still have access to them and will
# allow a clean shutdown while still allowing removal of all on disk
# log files.
# Since tmpfs file systems live on memory the contents copied to them
# will disappear on shutdown
# 3. Section 3 of 'log directories' loop:
# Once the tmpfs file system has been mounted the original on-disk log
# directory will no longer be directly accessible. In order to access
# and clear any log files from these disk areas we need to re-mount or
# bind mount the device or file system on which the log directory is
# residing to an alternate location. We can then access and remove
# any files from the disk by doing so from the alternate mount point.
#
# Static log files are removed directly at the end of the script
#
# Original log list taken from Libguestfs's sysprep_operation_logfiles.ml
# See https://github.com/libguestfs/libguestfs/tree/master/sysprep
set -o errexit
# Absolute path to guest log file directories
# All files under the given directories will be removed
logd_locations=(
# Log files and directories
"/var/log"
# GDM and session preferences
"/var/cache/gdm"
"/var/lib/AccountService/users"
# Fingerprint service files
"/var/lib/fprint"
# fontconfig caches
"/var/cache/fontconfig"
# man pages cache
"/var/cache/man"
)
# Absolute path to static log files that can be removed directly
logf_locations=(
# Logfiles configured by /etc/logrotate.d/*
"/var/named/data/named.run"
# Status file of logrotate
"/var/lib/logrotate.status"
# Installation files
"/root/install.log"
"/root/install.log.syslog"
"/root/anaconda-ks.cfg"
"/root/original-ks.cfg"
"/root/anaconda-post.log"
"/root/initial-setup-ks.cfg"
# Pegasus certificates and other files
"/etc/Pegasus/*.cnf"
"/etc/Pegasus/*.crt"
"/etc/Pegasus/*.csr"
"/etc/Pegasus/*.pem"
"/etc/Pegasus/*.srl"
)
# Set mountpoint used to access original on disk content
mntpnt_orig_logd="/mnt/orig_log_dir"
# Include hidden files in glob
shopt -s dotglob
# Since the current contents of the log directories will essentially be
# copied into memory, we need to ensure that we don't cause an out of
# memory condition for the guest. The limit of 128m should be extremely
# generous for most systems
sum_logd_space=0
for logd in ${logd_locations[@]}
do
if [ -d ${logd} ]; then
logd_space="$(du -sm ${logd} | cut -f1)"
else
logd_space=0
fi
sum_logd_space=$(( ${sum_logd_space} + ${logd_space} ))
if [ ${sum_logd_space} -gt 128 ]; then
echo "ERROR: Space for copying logs into memory > 128mb. Exiting"
exit 1
fi
done
# Test for tmpfs filesystem at /dev/shm creating one if it doesn't exist
# If /dev/shm is not present, attempt to create it
if ! mount -l -t tmpfs | grep /dev/shm &>/dev/null; then
[[ -d /dev/shm ]] || mkdir /dev/shm && chmod 1777 /dev/shm
mount -t tmpfs -o defaults,size=128m tmpfs /dev/shm
fi
# Remove logs from given log directories
for logd in ${logd_locations[@]}
do
if [ -d ${logd} ]; then
# Test if the path or its parents are already on tmpfs
logd_path="${logd}"
on_tmpfs=false
while [[ ${logd_path:0:1} = "/" ]] && [[ ${#logd_path} > 1 ]] && \
[[ ${on_tmpfs} = false ]]
do
defifs=${IFS}
IFS=$'\n' # Set for convenience with mount output
for mountpoint in $(mount -l -t tmpfs | cut -d' ' -f3)
do
if [ "${mountpoint}" == "${logd_path}" ]; then
on_tmpfs=true
continue # No need to test further
fi
done
IFS=${defifs} # Restore the default IFS and split behaviour
logd_path=${logd_path%/*} # Test parent on next iteration
done
if [ "${on_tmpfs}" = false ]; then
# Initialise/reset var used to store where log dir is located
logd_located_on=""
# If log directory is a mounted partition we need the device
defifs=${IFS} && IFS=$'\n' # Set for convenience with df output
for line in $(df | tr -s ' ')
do
# Sixth column of df output is the mountpoint
if echo ${line} | cut -d' ' -f6 | grep ^${logd}$ &>/dev/null; then
# First column of df output is the device
logd_located_on="$(echo ${line} | cut -d' ' -f1)"
fi
done
IFS=${defifs} # Restore the default IFS and split behaviour
# If the log directory is not a mounted partition it must be on
# the root file system
[[ "x${logd_located_on}" = "x" ]] && logd_located_on="/"
# Recreate the log directory under /dev/shm (on tmpfs)
shmlogd="/dev/shm/${logd}"
mkdir -p ${shmlogd}
chmod 1777 ${shmlogd}
# Copy all files from original log dir to new tmpfs based dir
files=(${logd}/*) # Array allows wildcard/glob with [[ test ]]
[[ -e ${files} ]] && cp -pr ${logd}/* ${shmlogd}
# Replace the original disk based log directory structure with
# the ephemeral tmpfs based storage by mounting it over the top of
# the original log directories location on the file system
mount --bind ${shmlogd} ${logd}
# Create a mount point from which the contents of the original
# on-disk log directory can be accessed post mount of the tmpfs
# file system
mkdir ${mntpnt_orig_logd}
# Mount or bind mount in order to access the original on disk logs
if [ ${logd_located_on} = "/" ]; then
# Temp file system is a folder on the root file system
mount_opts="--bind"
# Contents will be under mount point + original path e.g
# /mountpoint/var/tmp
logd_path="${mntpnt_orig_logd}/${logd}"
else
# Temp file system is a disk partition
mount_opts=""
# Contents will be directly available under the mount point
logd_path="${mntpnt_orig_logd}"
fi
# Mount the device holding the temp file system or bind mount the
# root file system
mount ${mount_opts} ${logd_located_on} ${mntpnt_orig_logd}
# The lastlog file cannot be created on demand for some reason
# and errors occur if /var/log/lastlog is missing. So, check if
# '/var/log/lastlog' exists and store the location so we can
# recreate later
if [ "${logd}" == "/var/log" ]; then
lastlog="$(find ${logd_path} -type f -name lastlog)"
fi
# Delete all files from the on-disk log directory
find "${logd_path}" -type f | xargs -I FILE rm -f FILE
# Recreate the /var/log/lastlog file if required
if [[ "${logd}" == "/var/log" ]] && [[ "x${lastlog}" != "x" ]]; then
touch "${lastlog}"
fi
# Cleanup
umount ${mntpnt_orig_logd} && rm -rf ${mntpnt_orig_logd}
fi
fi
done
# Remove static log files and files that may be removed directly
for file in ${logf_locations[@]}
do
[[ -e ${file} ]] && rm -f ${file}
done
exit 0