12

A junior team member did a nasty chmod -R 777 in /etc/ and cause SSH cannot login remotely in a Ubuntu server. Now I fixed this login issue by manually set the correct file permissions on /etc/ssh/*, /etc/sudoers, /etc/ssl/* by comparing other normal system. But there are so many other files which may cause future issues.

I am thinking to use rsync to do the work, but don't want it to sync file contents, just permissions, no more work.

Is that possible? I see rsync has -a option but it does too much.

Oleg Muravskiy
  • 705
  • 5
  • 8
kyrre
  • 327
  • 3
  • 9
  • What you are asking is possible, but not with rsync, I'm afraid. – 4ae1e1 Apr 15 '15 at 10:27
  • Thank you for replying, so what's that? I am open for other tools. – kyrre Apr 16 '15 at 01:30
  • Well, you can write a script to read the attributes of files on one system and set the attributes on the other. Nothing magical. – 4ae1e1 Apr 16 '15 at 01:56
  • http://samba.2283325.n4.nabble.com/Using-rsync-to-just-resync-permissions-and-ownership-td4648100.html – Tim G Apr 29 '15 at 17:26
  • Also see [fixunix.com](http://fixunix.com/unix/88355-rsync-permissions-*only*.html) for a discussion developing a shell script that applies permissions of a set of files to their copies – Daniel Böhmer May 07 '16 at 23:01
  • You might have better luck with the Unix & Linux community –  Dec 01 '17 at 13:11

2 Answers2

19

If you have the "normal" content of /etc available on the same system (like mounted in some other directory, let's say /mnt/correct/etc), you could use the --reference parameter to chmod and chown commands, and combine it with find that is started from the "normal" directory:

$ cd /mnt/correct/etc
$ find . ! -type l -exec chown -v --reference='{}' /etc/'{}' \;
$ find . ! -type l -exec chmod -v --reference='{}' /etc/'{}' \;

(I'm assuming you're on a UNIX system with GNU coreutils versions of chmod and chown.)

The "! -type l" condition in find excludes symbolic links, because otherwise chmod will use the link's permissions to change the file the link points to (and same applies to chown).

Oleg Muravskiy
  • 705
  • 5
  • 8
  • 2
    This works very well but I just wanted to point out that you should `chown` _before_ doing the `chmod` because chown will clear setuid/setgid bits. – CR. Dec 31 '17 at 05:27
1

Please note you can also try something that won't necessarily make you need to copy files from one place to another (depending on the filesize it may be desired)

You could use a mix of find and some grepping to generate a shell script to be executed on the host where you need to fix permissions.. you could use the same approach to generate a script for changing users/groups as well.. for example:

# find . -printf 'chmod %m %p #%M\n' | sort -k3 | grep -Pi '\s+\S*s\S*$'  > /var/tmp/fix_permissions.bash 
# bash /var/tmp/fix_permissions.bash

In the example above, what it does is to list all the files with their attributes in this format:

chmod 2755 ./addfs_7.1.0/bin #drwxr-sr-x
chmod 2755 ./addfs_7.1.0/config #drwxr-sr-x
chmod 2755 ./addfs_7.1.0 #drwxr-sr-x
chmod 2755 ./addfs_7.1.0/install #drwxr-sr-x
chmod 2755 ./addfs_7.1.0/library.dda #drwxr-sr-x
chmod 2755 ./addfs_7.1.0/library #drwxr-sr-x
chmod 2755 ./autosimimport #drwxr-sr-x

And in my case I only want to sync those with the 's' flag, so I filter with grep -Pi '\s+\S*s\S*$'. Sort was there as well because I had to compare the files in the other host.

TLDR

If you just want to apply all the permissions with no filtering or comparing:

  1. Create a script with the correct permissions on the "base" host

    find . -printf 'chmod %m %p\n' > /var/tmp/fix_permissions.sh

  2. Execute the script in the other host

    bash /var/tmp/fix_permissions.sh

pimguilherme
  • 1,050
  • 11
  • 15
  • 1
    This was helpful when I didn't have rights to NFS mount between the systems to use `chmod --reference`, thanks! I'm a little surprised rsync doesn't have this ability itself. – S'pht'Kr Mar 01 '22 at 16:05
  • 1
    this is a good idea, but misses some corner cases like chmod of a symbolic link and file names with spaces in them. – Joseph Tingiris Sep 17 '22 at 16:29
  • @JosephTingiris, granted! hopefully the approach can be tuned to more specific use cases like using some quote escaping within the printf command for file names with spaces: `find . -printf "chmod %m '%p'\n" > /var/tmp/fix_permissions.sh`.. as for symbolic links, hopefully some tuning of the find parameters can provide the desired results – pimguilherme Oct 07 '22 at 12:39