diff --git a/setup/container/docker_janitor b/setup/container/docker_janitor index 285a9e09e..ddfb4da28 100755 --- a/setup/container/docker_janitor +++ b/setup/container/docker_janitor @@ -24,16 +24,6 @@ readonly containers=$(docker ps -qa) for container in $containers; do echo "Cleaning up $container" - if tmpdir=$(docker inspect --format='{{index .Volumes "/tmp"}}' $container); then - echo -e "\tRemoving old files from $tmpdir" - - if [[ $tmpdir == /home/yellowtent/data/docker/volumes/* ]]; then - find $tmpdir -mtime +10 -exec rm -rf {} + # 10 days max. note we cannot use atime because this is not a tmpfs - else - echo -e "\tInternal error in script. /tmp is mounted at unexpected location $tmpdir" - fi - fi - if logdir=$(docker inspect --format='{{index .Volumes "/var/log"}}' $container); then echo -e "\tLogrotate files under $logdir" diff --git a/src/cron.js b/src/cron.js index 5fb9f493a..fcfa5b1f9 100644 --- a/src/cron.js +++ b/src/cron.js @@ -19,7 +19,8 @@ var gAutoupdaterJob = null, gAppUpdateCheckerJob = null, gHeartbeatJob = null, gBackupJob = null, - gCleanupTokensJob = null; + gCleanupTokensJob = null, + gDockerVolumeCleanerJob = null; var gInitialized = false; @@ -92,6 +93,14 @@ function recreateJobs(unusedTimeZone, callback) { timeZone: allSettings[settings.TIME_ZONE_KEY] }); + if (gDockerVolumeCleanerJob) gDockerVolumeCleanerJob.stop(); + gDockerVolumeCleanerJob = new CronJob({ + cronTime: '00 00 */12 * * *', // every 12 hours + onTick: janitor.cleanupDockerVolumes, + start: true, + timeZone: allSettings[settings.TIME_ZONE_KEY] + }); + autoupdatePatternChanged(allSettings[settings.AUTOUPDATE_PATTERN_KEY]); if (callback) callback(); @@ -149,6 +158,9 @@ function uninitialize(callback) { gCleanupTokensJob.stop(); gCleanupTokensJob = null; + gDockerVolumeCleanerJob.stop(); + gDockerVolumeCleanerJob = null; + gInitialized = false; callback(); diff --git a/src/janitor.js b/src/janitor.js index a9801ed07..9aa610fd1 100644 --- a/src/janitor.js +++ b/src/janitor.js @@ -4,10 +4,12 @@ var assert = require('assert'), async = require('async'), authcodedb = require('./authcodedb.js'), debug = require('debug')('box:src/janitor'), + docker = require('./docker.js'), tokendb = require('./tokendb.js'); exports = module.exports = { - cleanupTokens: cleanupTokens + cleanupTokens: cleanupTokens, + cleanupDockerVolumes: cleanupDockerVolumes }; function ignoreError(func) { @@ -47,8 +49,53 @@ function cleanupExpiredAuthCodes(callback) { function cleanupTokens(callback) { assert.strictEqual(typeof callback, 'function'); + debug('Cleaning up expired tokens'); + async.series([ ignoreError(cleanupExpiredTokens), ignoreError(cleanupExpiredAuthCodes) ], callback); } + +function cleanupTmpVolume(containerId, callback) { + assert.strictEqual(typeof containerId, 'string'); + assert.strictEqual(typeof callback, 'function'); + + var cmd = 'find /tmp -mtime +10 -exec rm -rf {} +'.split(' '); // 10 days old + + debug('cleanupTmpVolume %s', containerId); + + docker.getContainer(containerId).exec({ Cmd: cmd, AttachStdout: true, AttachStderr: true, Tty: false }, function (error, execContainer) { + if (error) { + debug('Failed to exec container : %s', error.message); + return callback(); // intentionally ignore error + } + + execContainer.start(function(err, stream) { + if (error) { + debug('Failed to start exec container : %s', error.message); + return callback(); // intentionally ignore error + } + + stream.on('error', callback); + stream.on('end', callback); + + stream.setEncoding('utf8'); + stream.pipe(process.stdout); + }); + }); +} + +function cleanupDockerVolumes(callback) { + assert.strictEqual(typeof callback, 'function'); + + debug('Cleaning up docker volumes'); + + docker.listContainers(function (error, containers) { + if (error) return callback(error); + + async.eachSeries(containers, function (containerInfo, iteratorDone) { + cleanupTmpVolume(containerInfo.Id, iteratorDone); + }, callback); + }); +}