@@ -18,6 +18,7 @@ import (
1818const (
1919 flagKeep = "keep"
2020 flagBinaryKillByAutoBackup = "binary"
21+ flagGenSetup = "gen-setup"
2122)
2223
2324const (
@@ -31,14 +32,19 @@ const (
3132
3233func GetAutoBackupPrivValidatorStateCmd () * cobra.Command {
3334 var cmd = & cobra.Command {
34- Use : commandAutoBackupPrivValidatorState + " [node_home]" ,
35- Short : "Designed to be run as a service, it will automatically backup the `priv_validator_state.json`, and kill the node process if the content of the file is decreased" ,
36- Args : cobra .ExactArgs (1 ),
35+ Use : commandAutoBackupPrivValidatorState + " [node_home]" ,
36+ Aliases : []string {"auto-backup-pvs" , "auto-backup-priv-validator-state" },
37+ Short : "Designed to be run as a service, it will automatically backup the `priv_validator_state.json`, and kill the node process if the content of the file is decreased" ,
38+ Args : cobra .ExactArgs (1 ),
3739 Run : func (cmd * cobra.Command , args []string ) {
3840 utils .MustNotUserRoot ()
3941
40- nodeHomeDirectory := strings .TrimSpace (args [0 ])
42+ nodeHomeDirectory := strings .TrimSuffix ( strings . TrimSpace (args [0 ]), "/" )
4143 validateNodeHomeDirectory (nodeHomeDirectory )
44+ if ! strings .Contains (nodeHomeDirectory , "/" ) {
45+ utils .ExitWithErrorMsg ("ERR: node home directory must be absolute path, eg: /home/user/.nodeHome" )
46+ return
47+ }
4248
4349 currentUser , err := user .Current ()
4450 if err != nil {
@@ -47,6 +53,11 @@ func GetAutoBackupPrivValidatorStateCmd() *cobra.Command {
4753 }
4854 userHomeDir := currentUser .HomeDir
4955
56+ if ! strings .HasPrefix (nodeHomeDirectory , userHomeDir ) {
57+ utils .ExitWithErrorMsg ("ERR: node home directory must be under user home directory:" , userHomeDir )
58+ return
59+ }
60+
5061 backupDstPath := path .Join (userHomeDir , fmt .Sprintf (".backup_priv_validator_state_%s" , constants .BINARY_NAME ))
5162 createBackupDirIfNotExists (backupDstPath )
5263 fmt .Println ("INF: backup directory:" , backupDstPath )
@@ -82,6 +93,11 @@ func GetAutoBackupPrivValidatorStateCmd() *cobra.Command {
8293 _ , binaryNameToKill := path .Split (binaryPathToKill )
8394 fmt .Println ("INF: binary to kill:" , binaryNameToKill , "at" , binaryPathToKill )
8495
96+ if cmd .Flags ().Changed (flagGenSetup ) {
97+ genSetupThenExit (nodeHomeDirectory , binaryPathToKill , keepRecent , currentUser )
98+ return
99+ }
100+
85101 privValStateJsonFilePath := path .Join (nodeHomeDirectory , "data" , "priv_validator_state.json" )
86102 fmt .Println ("INF: priv_validator_state.json file path:" , privValStateJsonFilePath )
87103
@@ -279,6 +295,7 @@ How to recover:
279295
280296 cmd .Flags ().Int (flagKeep , 3 , "Keep the last N backups" )
281297 cmd .Flags ().String (flagBinaryKillByAutoBackup , "" , "Absolute path of the chain binary to be killed by process when priv_validator_state.json has problem" )
298+ cmd .Flags ().Bool (flagGenSetup , false , "Display guide to setup instead of running business logic" )
282299
283300 return cmd
284301}
@@ -453,3 +470,40 @@ func loadLatestBackupPrivValidatorStateOrExitWithErr(backupDstPath string) types
453470
454471 return * pvs
455472}
473+
474+ func genSetupThenExit (nodeHomeDirectory , binaryPathToKill string , keepRecent int , currentUser * user.User ) {
475+ const serviceFileName = "auto-backup-pvs"
476+ fmt .Println ("Input chain name (eg: Cosmos Hub):" )
477+ chainName := utils .ReadText (false )
478+ fmt .Println ("Mainnet or Testnet?" )
479+ networkType := utils .ReadText (false )
480+ fmt .Println ("INF: setup guide:" )
481+ fmt .Println ("1. Create service file" )
482+ fmt .Println ("> sudo vi /etc/systemd/system/" + serviceFileName + ".service" )
483+ fmt .Printf (`[Unit]
484+ Description=Auto backup priv_validator_state.json for Validator on %s %s
485+ After=network.target
486+ #
487+ [Service]
488+ User=%s
489+ ExecStart=%s/go/bin/%s start %s --%s %s --%s %d
490+ RestartSec=1
491+ Restart=on-failure
492+ LimitNOFILE=1024
493+ #
494+ [Install]
495+ WantedBy=multi-user.target
496+ ` , chainName , networkType , currentUser .Username , currentUser .HomeDir , constants .BINARY_NAME , nodeHomeDirectory , flagBinaryKillByAutoBackup , binaryPathToKill , flagKeep , keepRecent )
497+ fmt .Println ("2. Setup visudo" )
498+ fmt .Println ("> sudo visudo" )
499+ fmt .Printf (strings .ReplaceAll (strings .ReplaceAll (`# Allow user @USER@ to manage @SVC@ service
500+ @USER@ ALL= NOPASSWD: /usr/bin/systemctl start @SVC@
501+ @USER@ ALL= NOPASSWD: /usr/bin/systemctl stop @SVC@
502+ @USER@ ALL= NOPASSWD: /usr/bin/systemctl restart @SVC@
503+ @USER@ ALL= NOPASSWD: /usr/bin/systemctl enable @SVC@ # Do not allow disable
504+ @USER@ ALL= NOPASSWD: /usr/bin/systemctl status @SVC@
505+ ` , "@USER@" , currentUser .Username ), "@SVC@" , serviceFileName ))
506+ fmt .Println ("3. Enable service to automatically run at startup" )
507+ fmt .Println ("> sudo systemctl daemon-reload && sudo systemctl enable " + serviceFileName + ".service" )
508+ os .Exit (0 )
509+ }
0 commit comments