@@ -504,11 +504,6 @@ func (c *Client) StopService(composeFiles []string) error {
504504
505505// Stop the Rocket Pool service and remove the config folder
506506func (c * Client ) TerminateService (composeFiles []string , configPath string ) error {
507- // Get the command to run with root privileges
508- rootCmd , err := c .getEscalationCommand ()
509- if err != nil {
510- return fmt .Errorf ("could not get privilege escalation command: %w" , err )
511- }
512507
513508 // Terminate the Docker containers
514509 cmd , err := c .compose (composeFiles , "down -v" )
@@ -526,8 +521,9 @@ func (c *Client) TerminateService(composeFiles []string, configPath string) erro
526521 return fmt .Errorf ("error loading Rocket Pool directory: %w" , err )
527522 }
528523 fmt .Printf ("Deleting Rocket Pool directory (%s)...\n " , path )
529- cmd = fmt .Sprintf ("%s rm -rf %s" , rootCmd , path )
530- _ , err = c .readOutput (cmd )
524+ cmd = fmt .Sprintf ("rm -rf %s" , path )
525+ // The directory contains root-owned paths, so delete it as root
526+ _ , err = c .readOutputSudo (cmd )
531527 if err != nil {
532528 return fmt .Errorf ("error deleting Rocket Pool directory: %w" , err )
533529 }
@@ -882,11 +878,6 @@ func (c *Client) RunNethermindPruneStarter(executionContainerName string, pruneS
882878
883879// Deletes the node wallet and all validator keys, and restarts the Docker containers
884880func (c * Client ) PurgeAllKeys (composeFiles []string ) error {
885- // Get the command to run with root privileges
886- rootCmd , err := c .getEscalationCommand ()
887- if err != nil {
888- return fmt .Errorf ("could not get privilege escalation command: %w" , err )
889- }
890881
891882 // Get the config
892883 cfg , _ , err := c .LoadConfig ()
@@ -912,8 +903,9 @@ func (c *Client) PurgeAllKeys(composeFiles []string) error {
912903 return fmt .Errorf ("error loading wallet path: %w" , err )
913904 }
914905 fmt .Println ("Deleting wallet..." )
915- cmd := fmt .Sprintf ("%s rm -f %s" , rootCmd , walletPath )
916- _ , err = c .readOutput (cmd )
906+ cmd := fmt .Sprintf ("rm -f %s" , walletPath )
907+ // The file is owned by root, so delete as root
908+ _ , err = c .readOutputSudo (cmd )
917909 if err != nil {
918910 return fmt .Errorf ("error deleting wallet: %w" , err )
919911 }
@@ -924,8 +916,9 @@ func (c *Client) PurgeAllKeys(composeFiles []string) error {
924916 return fmt .Errorf ("error loading password path: %w" , err )
925917 }
926918 fmt .Println ("Deleting password..." )
927- cmd = fmt .Sprintf ("%s rm -f %s" , rootCmd , passwordPath )
928- _ , err = c .readOutput (cmd )
919+ cmd = fmt .Sprintf ("rm -f %s" , passwordPath )
920+ // The file is owned by root, so delete as root
921+ _ , err = c .readOutputSudo (cmd )
929922 if err != nil {
930923 return fmt .Errorf ("error deleting password: %w" , err )
931924 }
@@ -936,13 +929,19 @@ func (c *Client) PurgeAllKeys(composeFiles []string) error {
936929 return fmt .Errorf ("error loading validators folder path: %w" , err )
937930 }
938931 fmt .Println ("Deleting validator keys..." )
939- cmd = fmt .Sprintf ("%s rm -rf %s/*" , rootCmd , validatorsPath )
940- _ , err = c .readOutput (cmd )
932+ cmd = fmt .Sprintf ("rm -rf %s/*" , validatorsPath )
933+ // The validators path can be created by the smartnode daemon (owned by root, 0600)
934+ // So delete its contents as root, otherwise the * won't expand.
935+ // NB: we delete the contents of the folder instead of recreating the folder
936+ // This way, if the drive is full, we don't release the directory inode and fail to recreate it.
937+ _ , err = c .readOutputSudo (cmd )
941938 if err != nil {
942939 return fmt .Errorf ("error deleting validator keys: %w" , err )
943940 }
944- cmd = fmt .Sprintf ("%s rm -rf %s/.[a-zA-Z0-9]*" , rootCmd , validatorsPath )
945- _ , err = c .readOutput (cmd )
941+ // Also delete hidden files
942+ cmd = fmt .Sprintf ("rm -rf %s/.[a-zA-Z0-9]*" , validatorsPath )
943+ // also as root, so bash can expand the regex
944+ _ , err = c .readOutputSudo (cmd )
946945 if err != nil {
947946 return fmt .Errorf ("error deleting hidden files in validator folder: %w" , err )
948947 }
@@ -977,31 +976,6 @@ func (c *Client) SetClientStatusFlags(ignoreSyncCheck bool, forceFallbacks bool)
977976 c .forceFallbacks = forceFallbacks
978977}
979978
980- // Get the command used to escalate privileges on the system
981- func (c * Client ) getEscalationCommand () (string , error ) {
982- // Check for sudo first
983- sudo := "sudo"
984- exists , err := c .checkIfCommandExists (sudo )
985- if err != nil {
986- return "" , fmt .Errorf ("error checking if %s exists: %w" , sudo , err )
987- }
988- if exists {
989- return sudo , nil
990- }
991-
992- // Check for doas next
993- doas := "doas"
994- exists , err = c .checkIfCommandExists (doas )
995- if err != nil {
996- return "" , fmt .Errorf ("error checking if %s exists: %w" , doas , err )
997- }
998- if exists {
999- return doas , nil
1000- }
1001-
1002- return "" , fmt .Errorf ("no privilege escalation command found" )
1003- }
1004-
1005979func (c * Client ) checkIfCommandExists (command string ) (bool , error ) {
1006980 // Run `type` to check for existence
1007981 cmd := fmt .Sprintf ("type %s" , command )
@@ -1390,6 +1364,26 @@ func (c *Client) printOutput(cmdText string) error {
13901364
13911365}
13921366
1367+ // Run a command as root and return its output
1368+ func (c * Client ) readOutputSudo (rootCmdText string ) ([]byte , error ) {
1369+ var escCmd string
1370+ for _ , escalationCommand := range []string {"sudo" , "doas" } {
1371+ exists , err := c .checkIfCommandExists (escalationCommand )
1372+ if err != nil {
1373+ return nil , fmt .Errorf ("error checking if %s exists: %w" , escalationCommand , err )
1374+ }
1375+ if exists {
1376+ escCmd = escalationCommand
1377+ break
1378+ }
1379+ }
1380+ if escCmd == "" {
1381+ return nil , fmt .Errorf ("no privilege escalation command found" )
1382+ }
1383+
1384+ return c .readOutput (fmt .Sprintf ("%s bash -c %s" , escCmd , shellescape .Quote (rootCmdText )))
1385+ }
1386+
13931387// Run a command and return its output
13941388func (c * Client ) readOutput (cmdText string ) ([]byte , error ) {
13951389
0 commit comments