pyinfra
pyinfra copied to clipboard
server.crontab() not identifying cronjobs
Describe the bug
If this is not a bug I am horribly confused on how this is actually supposed to work. 🙃
If an unidentified cronjob exists in your crontab and you attempt to identify this cronjob with the cron_name
argument, this does not add an identifier to the cronjob. You must then make another call to server.crontab()
with the same cron_name
if you want to make changes to the cronjob. This time however, instead of overwriting the existing cronjob that you just tried to identify, server.crontab()
will create a new entry in your crontab - appending it to the end of the file - leaving you with the cronjob you initially tried to identify as well as the new cronjob with the identifier you tried to apply to the initial cronjob.
To Reproduce
Have a crontab with some cronjobs in it that aren't identified by PyInfra, then run server.crontab()
against your crontab in an attempt to identify the cronjobs, and then modify them afterwards.
- Operation code & usage
server.crontab(
name="Identify Cron",
command=f"/usr/bin/php{php_version} {old_estore_dir}/bin/magento cron:run 2>&1 \
| grep -v \"Ran jobs by schedule\" >> {old_estore_dir}/var/log/magento.cron.log",
minute="*",
hour="*",
month="*",
day_of_week="*",
day_of_month="*",
present=True,
user=f"{username}",
cron_name=f"{site}_cron",
_sudo=True,
)
server.crontab(
name="Modify Cron",
command=f"/usr/bin/php{php_version} {estore_dir}/bin/magento cron:run 2>&1 \
| grep -v \"Ran jobs by schedule\" >> {estore_dir}/var/log/magento.cron.log",
minute="*",
hour="*",
month="*",
day_of_week="*",
day_of_month="*",
present=True,
user=f"{username}",
cron_name=f"{site}_cron",
_sudo=True,
)
If I attempt to identify and modify either of the cronjobs, I get a brand new cronjob appended to the end of the file as shown, with the cron identifier. In this example I tried to edit the staging_cron
Before
* * * * * /usr/bin/php8.2 /opt/<name>/apps/prod/estore.e483eac1/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /opt/<name>/apps/prod/estore.e483eac1/var/log/magento.cron.log
* * * * * /usr/bin/php8.2 /opt/<name>/apps/staging/estore.1312e8dd/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /opt/<name>/apps/staging/estore.1312e8dd/var/log/magento.cron.log
After
* * * * * /usr/bin/php8.2 /opt/<name>/apps/prod/estore.e483eac1/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /opt/<name>/apps/prod/estore.e483eac1/var/log/magento.cron.log
* * * * * /usr/bin/php8.2 /opt/<name>/apps/staging/estore.1312e8dd/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /opt/<name>/apps/staging/estore.1312e8dd/var/log/magento.cron.log
# pyinfra-name=staging_cron
* * * * * /usr/bin/php8.2 /opt/<name>/apps/staging/estore.656bc6af/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /opt/<name>/apps/staging/estore.656bc6af/var/log/magento.cron.log
Expected behavior
The cronjob should be identified with the first call to server.crontab()
, prepending the cron_name
identifier/comment on the line above the cronjob. Then, the second call to server.crontab()
should overwrite this cronjob with the new contents if the same cron_name
is used, not appending a new cronjob to the end of the file, and not leaving the initial cronjob behind.
Meta
System: Linux
Platform: Linux-5.15.153.1-microsoft-standard-WSL2-x86_64-with-glibc2.35
Release: 5.15.153.1-microsoft-standard-WSL2
Machine: x86_64
pyinfra: v3.1
click: v8.1.7
configparser: v7.1.0
distro: v1.9.0
gevent: v24.2.1
jinja2: v3.1.4
packaging: v24.1
paramiko: v3.4.1
python-dateutil: v2.9.0.post0
pywinrm: v0.5.0
setuptools: v73.0.1
typeguard: v4.3.0
typing-extensions: v4.12.2
wheel: v0.44.0
Executable: /home/<name>/<project>/env/bin/pyinfra
Python: 3.10.12 (CPython, GCC 11.4.0)
-
How was pyinfra installed? Pip
-
Debug info:
--> Starting operation: Identify Cron
[pyinfra.api.operations] Starting operation {'Identify Cron'} on @local
[pyinfra.api.facts] Getting fact: server.Crontab (user=<name>) (ensure_hosts: None)
[pyinfra.connectors.local] --> Running command on localhost: sudo -H -n sh -c '! command -v crontab >/dev/null || crontab -l -u <name> || true'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 0
[pyinfra.api.facts] [@local] Loaded fact server.Crontab (user=<name>)
[pyinfra.api.host] [@local] noop: crontab /usr/bin/php8.2 /opt/<name>/apps/staging/estore.1312e8dd/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /opt/<name>/apps/staging/estore.1312e8dd/var/log/magento.cron.log exists
[@local] No changes
--> Starting operation: Modify Cron
[pyinfra.api.operations] Starting operation {'Modify Cron'} on @local
[pyinfra.api.facts] Getting fact: server.Crontab (user=<name>) (ensure_hosts: None)
[pyinfra.connectors.local] --> Running command on localhost: sudo -H -n sh -c '! command -v crontab >/dev/null || crontab -l -u <name> || true'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 0
[pyinfra.api.facts] [@local] Loaded fact server.Crontab (user=<name>)
[pyinfra.connectors.local] --> Running command on localhost: sudo -H -n sh -c 'crontab -l -u <name>> /tmp/pyinfra-99800753387583ff6590a828b5571df23d46c9b6'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 0
[pyinfra.connectors.local] --> Running command on localhost: sudo -H -n sh -c 'echo '"'"''"'"' >> /tmp/pyinfra-99800753387583ff6590a828b5571df23d46c9b6'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 0
[pyinfra.connectors.local] --> Running command on localhost: sudo -H -n sh -c 'echo '"'"'# pyinfra-name=staging_cron'"'"' >> /tmp/pyinfra-99800753387583ff6590a828b5571df23d46c9b6'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 0
[pyinfra.connectors.local] --> Running command on localhost: sudo -H -n sh -c 'echo '"'"'* * * * * /usr/bin/php8.2 /opt/<name>/apps/staging/estore.656bc6af/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /opt/<name>/apps/staging/estore.656bc6af/var/log/magento.cron.log'"'"' >> /tmp/pyinfra-99800753387583ff6590a828b5571df23d46c9b6'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 0
[pyinfra.connectors.local] --> Running command on localhost: sudo -H -n sh -c 'crontab -u <name> /tmp/pyinfra-99800753387583ff6590a828b5571df23d46c9b6'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 0
[@local] Success