twpayne / chezmoi

Manage your dotfiles across multiple diverse machines, securely.
https://www.chezmoi.io/
MIT License
12.9k stars 478 forks source link

How to set an expiration time for "run_onchange_" script? #3618

Closed sunn4room closed 6 months ago

sunn4room commented 6 months ago

Is your feature request related to a problem? Please describe.

There is a need to run a script after a specified time. For example, I want to upgrade my ArchLinux packages in a week after the last time I upgraded. But for now, chezmoi couldn't do this gracefully.

Describe the solution you'd like

I expect a new prefix "in_" for chezmoi script. For example, write a script named "run_onchange_in_7d_upgrade-archlinux-packages.sh"

Additional

If there is a solution that I don't know, please tell me. Thanks !

bradenhilton commented 6 months ago

You can get the current week of the year with date +%V.

If you convert run_onchange_upgrade-archlinux-packages.sh to a template by renaming it to run_onchange_upgrade-archlinux-packages.sh.tmpl, you can place this somewhere in the file

# {{ output "date" "+%V" | trim }}

and it should re-run the script when the week number changes.

You can also approximate this with template functions:

# {{ min (ceil (divf now.YearDay 7)) 52 }}
sunn4room commented 6 months ago

@bradenhilton

You can get the current week of the year with date +%V.

This is my temporary solution for now. But this solution has a drawback.

Every Monday I upgrade. It's possible that this script was modified and executed on Sunday. There is unnecessary to run on next Monday.

I think it's better that chezmoi support "in_" prefix.

bradenhilton commented 6 months ago

What are you trying to accomplish with this script?

If you're using it to install packages, it should be sufficient that it runs every time it is changed, in order to trigger the installation of the package(s) that have been added. What benefit would you gain from also running it weekly?

If you're using it to run pacman -Syu, you're almost certainly better off using something like cron to run it weekly.

Have I misunderstood something?

sunn4room commented 6 months ago

@bradenhilton What are you trying to accomplish with this script?

with "run_onchange_upgrade.sh.tmpl"

#!/bin/bash
# {{ output "date" "+%V" | trim }}
sudo pacman -Syu neovim fzf git

This script will execute in two situations:

with "run_onchange_in_7d_upgrade.sh" if chezmoi supported.

#!/bin/bash
sudo pacman -Syu neovim fzf git

This script will execute in two situations:

final

This is the main difference.

sunn4room commented 6 months ago

I just want a feature that chezmoi remind me to execute a script after a specified time since the last time I executed it.

onchange_ and cron couldn't do this.

twpayne commented 6 months ago

As @bradenhilton says, if you want to run commands periodically then use cron. It is not chezmoi's job to do this.

You can find the last time that chezmoi ran your upgrade.sh script with the following command:

$ chezmoi state get-bucket --bucket=scriptState | jq '[.[] | select(.name=="upgrade.sh") | .runAt] | max'

Also

$ chezmoi status upgrade.sh

will include an R if chezmoi will run upgrade.sh next time you run chezmoi apply.

I suggest you use this information to write a script or plugin to achieve the effect you want.

chezmoi will not add a in_ attribute for scripts.

sunn4room commented 6 months ago

@twpayne if you want to run commands periodically then use cron, it is not chezmoi's job to do this.

It's not a periodical job, I just want to set an expiration time for "run_onchange_xxx" script. It's a common situation that a "run_onchange_xxx" script has not changed for a long time, and you need to re-run it to update something.

@twpayne You can find the last time that chezmoi ran your upgrade.sh script with the following command.

If you try to get the last time with the command during chezmoi apply, you will get an error message: timeout obtaining persistent state lock, is another instance of chezmoi running?

@twpayne I suggest you use this information to write a script or plugin to achieve the effect you want.

This is not easy to achieve. "run_onchangexxx.tmpl" script has two features, "onchange" and ".tmpl". It's possible that the execution of the script changes the output of template. For example with "run_onchange_foo.tmpl".

#!/bin/bash
# {{ output "wc" "-l" "/tmp/foo" | trim }}
echo "new line" >> /tmp/foo

After execution of foo, chezmoi status foo will always get a "R". Similarly, the execution of "run_onchange_upgrade.sh.tmpl" will change the last time of execution, also change the template.

@twpayne chezmoi will not add a in_ attribute for scripts.

Unfortunately, you closed this issue. My real purpose is to set an expiration time, not to add attribute. And I find it difficult to achieve.

Anyway, chezmoi is the most convenient tool I have ever used to manage dotfiles. Great job !

bradenhilton commented 6 months ago

@sunn4room Your script doesn't do what I suspect you think it does.

Upgrading individual packages with pacman -Sy <PACKAGE> is a partial upgrade, and partial upgrades are not supported. You will eventually break your system doing this.

https://wiki.archlinux.org/title/system_maintenance#Partial_upgrades_are_unsupported

pacman -Syu will perform a full system upgrade, so specifying individual packages is unnecessary.

There are a multitude of means by which you can remind yourself to perform a system upgrade after a certain amount of time has passed.

@twpayne I'm not a huge fan of the proposed in_ attribute, but something like adding .chezmoi.script (with the context of the currently running script) could be a partial solution, if possible. That would support something like

{{ .chezmoi.script.lastRunAt }}

or similar.

sunn4room commented 6 months ago

@bradenhilton Thanks for your response.

pacman -Syu is just an example, not my purpose. As I said.

It's a common situation that a "run_onchange_xxx" script has not changed for a long time, and you need to re-run it to update something.

@bradenhilton There are a multitude of means by which you can remind yourself to perform a system upgrade after a certain amount of time has passed.

It would be better if chezmoi support to set an expiration time. Isn't it?

@bradenhilton something like adding .chezmoi.script (with the context of the currently running script) could be a partial solution

I agree with you. It's really helpful.

twpayne commented 6 months ago

something like adding .chezmoi.script (with the context of the currently running script) could be a partial solution, if possible. That would support something like

{{ .chezmoi.script.lastRunAt }}

or similar.

Please open a new issue for this so we can track it.