Linux – tell find to to not restore initial working directory

findlinuxsudo

find isn't able to ‘restore initial working directory’ when run behind sudo -u if the initial working dir is not visible to the user find runs as. This causes find to always print an annoying Permission denied warning message:

$ pwd
/home/myuser
$ sudo -u apache find /home/otheruser -writable
find: failed to restore initial working directory: Permission denied

What is the best way to prevent find from printing this message?

One method is to change to a directory that the find user can restore, such as cd /, before running find. Ideally, I'd just like an option for find such as --do-not-restore-initial-working-directory but I guess that's not available. 😉

I'm mostly using RedHat-based distributions.

Best Answer

Cleanup appears to be a non-optional part of the execution of find.

https://github.com/Distrotech/findutils/blob/e6ff6b550f7bfe41fb3d72d4ff67cfbb398aa8e1/find/find.c#L231

in main in find.c

  cleanup ();
  return state.exit_status;
}

cleanup calls cleanup_initial_cwd

https://github.com/Distrotech/findutils/blob/e6ff6b550f7bfe41fb3d72d4ff67cfbb398aa8e1/find/util.c#L534

and cleanup_initial_cwd actually changes the directory

https://github.com/Distrotech/findutils/blob/e6ff6b550f7bfe41fb3d72d4ff67cfbb398aa8e1/find/util.c#L456

static void
cleanup_initial_cwd (void)
{
  if (0 == restore_cwd (initial_wd))
    {
      free_cwd (initial_wd);
      free (initial_wd);
      initial_wd = NULL;
    }
  else
    {
      /* since we may already be in atexit, die with _exit(). */
      error (0, errno,
         _("failed to restore initial working directory"));
      _exit (EXIT_FAILURE);
    }
}

You could try using a shell script that cds into / first, as you suggested. (there are some issues with this script, it can't handle multiple directories to search, for instance)

#!/bin/sh
path="$(pwd)/$1"
shift
cd /
exec find "$path" "$@"

You can also filter the output of stderr to remove the unwanted message

#!/bin/sh
exec 3>&2
exec 2>&1
exec 1>&3
exec 3>&-
3>&2 2>&1 1>&3 3>&- find "$@" | grep -v "^find: failed to restore initial working directory"
# not sure how to recover find's exit status
exit 0
Related Question