At Affinitic, we have many Plone sites on our servers and we wanted to pack their ZODB automatically.

Our goal is of course to do it without any downtime. It’s easy when you have a zeoserver, but you cannot use a packing script when there isn’t :

zc.lockfile.LockError: Couldn't lock 'instance/var/filestorage/Data.fs.lock'

We decided to simply do a wget on the ZMI packing form.
Here is the command to pack your main database (7 days) :

wget --max-redirect 0 --post-data='submit=Pack&days:float=7.0' http://user:password@localhost:8080/Control_Panel/Database/main/manage_pack

We wrapped this in a script to get meaningful exit code and this is deployed via Puppet to have a cron for each and every Plone instances. Even the user that is used to access the instance is created via Puppet with :

bin/instance adduser user password

Alternative method, not used for deployment reasons and using a Python script : https://www.nathanvangheem.com/news/automatically-pack-the-zodb

If it can help anyone …