- How to (Correctly) Change the UID and GID of a user/group in Linux
- Pre-requisites
- Modifying the UID and GID of the user and group
- Caveats
- Some more articles you might also be interested in …
- How To Change User ID (uid) In Linux?
- List Users ID
- Change User ID with usermod Command
- Change Group ID with groupmod Command
- Change Files and Folders Owner User ID
- Change Files and Folders Owner Group ID
- Изменение UID&GID пользователя и его файлов
- Полный код скрипта
How to (Correctly) Change the UID and GID of a user/group in Linux
Changing the UID and GID of a user might seem a trivial task to most of the system admins. But it’s not so trivial and it involves a lot more changes in the backend. In this post, we have outlined the exact steps to change the UID and GID of a user “user01”.
Username: user01 Group: group01 Existing UID: 800 Existing GID: 700 New UID: 900 New GID: 600
Pre-requisites
1. Make sure the user for which UID and GID is to be changed is currently not having any active process running in the system. To check the same use “ps” command. For example:
# ps -ef | grep user01 # ps -ef | grep 800
Note: In the “ps -ef” command UID are displayed. So make sure you grep for UID as well as the username for the user.
2. Take the backup of important files where UID and GID related information is stored. i.e. /etc/passwd and /etc/group.
# cp -p /etc/passwd /etc/passwd.bkp # cp -p /etc/group /etc/group.bkp
3. Verify the exisitng UID and GID of the user using the “id” command:
# id user01 uid=800(user01) gid=700(group01) groups=700(group01)
Modifying the UID and GID of the user and group
Once you have taken necessary backups and command outputs we can go ahead and change the UID and GID.
1. First change the GID of the group, group01:
2. Next, change the UID as well and GID of the user, user01:
# usermod -u 900 -g 600 user01
3. Verify the new UID and GID of the user:
# id user01 uid=900(user01) gid=600(group01) groups=600(group01)
Caveats
1. If there are multiple users in the group “group01”, after changing the GID of the group you will have to modify the other users as well along with the user01 as shown above.
2. Once you have changed the UID and GID, you will have to change the permissions of the files owned by the user/group as well. But the chown command also resets the SETUID and SETGID of the files, so you will need to manually change the permissions of these files later on. To find such files:
# find / -uid 900 -perm /6000 -ls # find / -gid 900 -perm /6000 -ls
3. To find the files owned by user01 and group01 and to change their permissions:
# find / -uid 800 -exec chown -v -h 900 '<>' \; # find / -gid 700 -exec chgrp -v 600 '<>' \;
The -h option is used to change the permissions of symbolic links as well.
Some more articles you might also be interested in …
How To Change User ID (uid) In Linux?
Every Linux user has a unique ID in order to distinguish them. These user IDs are used in different areas like permission, log, and kernel-level operations. The regular user ID’s start from 1000 and are incremented with every new user. You may ask if you can change the existing user ID in Linux. The answer is Yes you can change the existing user ID in Linux. For example, we can change the user ID from 1003 to 2003 in different ways.
List Users ID
The user information is stored in the /etc/passwd file and this file contains the USER ID information two. The User Id is provided as the 3rd column where the first column is the user name. We can list the users existing ID by printing this file with the cat command.
We can also filter the user specifically by using the grep command. In the following example, we only print the user “ismail” ID.
$ cat /etc/passwd | grep "ismail"
ismail:x:1000:1000:İsmail Baydan. /home/ismail:/bin/bash
The first 1000 is the user ID and the second 1000 is the group ID.
Change User ID with usermod Command
The usermod command is generally used to modify an existing user and related information in Linux. We can use the usermod command in order to change User ID. The -u option is used to provide the new User ID. The user name is provided as the last parameter to the usermod command.
In the following example, we change the user ismail Id to 2003.
$ sudo usermod -u 2003 ismail
Change Group ID with groupmod Command
Every user in Linux also has a private group with the same username by default. This group also has a group ID. We can use the groupmod command in order to change the user’s group ID. In the following example, we change the group ismail ID to 3003.
$ sudo groupmod -g 3003 ismail
Change Files and Folders Owner User ID
After changing the User ID its home directory ID and all contents of the user’s home directory is changed into the new ID. But in other files user ID is not changed automatically. To solve this issue the find command can be used to change to new User ID files owned by this user. We use the users old User Id to find files and use the chown command to set new user Id by refreshing with the new user name which sets the new User ID.
$ sudo find / -user 1003 -exec chown -h ismail <> \;
Change Files and Folders Owner Group ID
Similar to the user ID we can update the group ID for the user by using the chgrp command like below.
$ sudo find / -user 1003 -exec chgrp -h ismail <> \;
Изменение UID&GID пользователя и его файлов
Встала тут передо мной задача изменить UID и GID пользователя и правильно изменить владельца всех файлов.
Дело в том, что я работаю за двумя компьютерами попеременно, и файлы mysql лежат у меня на флешке. Получилось так, что id пользователя mysql на обоих компах отличается и мускл не может получить доступ к своим файлам. Присваивать права 0666 скучно, и по этому поводу я решил научиться грамотно изменять uid пользователя 🙂
- UID и GID не всегда одинаковы для пользователя и его группы
- Не все файлы принадлежат одновременно юзеру mysql и группе mysql: файлы для chown нужно искать отдельно
Изменение идентификатора пользователя и группы
Первый шаг — самый простой и о нём немало написано в интернетах. В первых двух строчках мы сохраняем полезные данные в переменных: имя, новый id и старый id для пользователя и для группы. Это нам пригодится в дальнейшем при поске файлов, а также упростит повторное использование скрипта. Всё указывается отдельно ввиду первого нюанса: UID и GID могут отличаться.
Дальше — тривиальное изменение идентификаторов стандартными командами Linux:
user =mysql new_uid = 600 old_uid =$ ( id -u $user )
group =mysql new_gid = 600 old_gid =$ ( id -g $user )
sudo usermod -u $new_uid $user
sudo groupmod -g $new_gid $group
Поиск осиротевших файлов
Если сейчас посмотреть на одну из папок с файлами mysql (например, ls -lah /var/lib/mysql ) то мы увидим, что файлы принадлежат подозрительному пользователю 112 и подозрительной группе 127. Такие файлы мы и будем искать с тем, чтобы удочерить их 🙂
Первое, что приходит в голову, это найти все файлы принадлежащие пользователю $old_uid или группе $old_group , и собрать все найденные файлы (при помощи xargs) в качества аргументов команде chown $user:$group . find выполняется от root чтобы гарантировать что он сможет забраться во все даже самые сурово защищённые папки и найдёт всё что от него требуется. xargs собирает строки из pipe и передаёт их команде, указанной в аргументе (chown). Замечу, что xargs может выполнить команду несколько раз во избежание слишком длинной строки аргументов.
Например, так:
Сразу обращу внимание на флаги find -print0 и xargs -0 : это такая борьба с возможными пробелами в именах файлов. Такие файлы могут быть восприняты chown ‘ом как два разных. Первый флаг заставляет find выводить каждый найденный файл с нулём в конце (символ конца строки в Си), а второй флаг сообщает xargs что ему нужно отделять файлы друг от друга не по переводу строки, а по этому самому нулю, что гарантирует верную обработку даже самых хитрых имён файлов 🙂
Однако такой способ не принесёт желаемого результата: некоторые файлы, владельцем которых был ‘mysql:root’ станут принадлежать ‘mysql:mysql’. А мы ведь договорились сделать всё предельно правильно 🙂 Следовательно, поиск по user и по group надо вести отдельно.
Можно выполнить подряд две команды find:
sudo find / -user $old_uid -print0 | xargs -0 sudo chown $user
sudo find / -group $old_gid -print0 | xargs -0 sudo chown : $group
и это уже будет намного ближе к истине, но тогда find ‘у придётся дважды шуршать по всему жёсткому диску.
Есть способ заставить команду find выполнить для нас две операции параллельно, сократив количество чтений с диска ровно в два раза. Для этого используем группировку условий и команд find круглыми скобками (не забывая их экранировать: иначе за них возьмётся шелл) и пославив между ними оператор «запятая»: тогда обе скобки будут выполняться для каждого файла.
Мы составим два отдельных файла: в первом будет список файлов с -user=$old_uid , а во втором — с -group=$old_gid , и обрабатывать эти файлы мы будет раздельно. Условие поиска теперь разделено на две выполняющися для каждого файла скобки, и в случае выполниния условия команда -fprint0 записывает в соответствующий временный файл путь к найденному осиротевшему файлу.
chownlist =$ ( tempfile ) chgrplist =$ ( tempfile )
sudo find / \
\ ( -user $old_uid -fprint0 » $chownlist » \ ) , \ ( -group $old_gid -fprint0 » $chgrplist » \ )
После недолгого поиска все файлы будут найдены.
Последний момент поиска: на форумах очень часто задаётся вопрос как исключить папки из списка find так, чтобы он туда вообще не залезал. Это делается при помощи сочетания условия -path «folder» и команды -prune , которая запрещает find залезать в папки, попавшие в условие. Мы исключим из поиска папки ‘/proc’ и ‘/sys’.
Для этого в условия добавим ещё одну группировку скобками, отделив их от уже существующих скобок оператором -or . Этот оператор выполнит первое условие, а второе — только если не сработало первое. Так, find проверит не попалась ли ему исключённая из листинга директория (в которой он не будет искать), и если нет — будет составлять списки файлов.
Делается это так:
chownlist =$ ( tempfile ) chgrplist =$ ( tempfile )
sudo find / \
\ ( \ ( -path «/proc» -or -path «/sys» \ ) -prune \ ) -or \ # исключение папок
\ ( \ ( -user $old_uid -fprint0 » $chownlist » \ ) , \ ( -group $old_gid -fprint0 » $chgrplist » \ ) \ )
Также в исключения можно внести путь к диску с бекапом (он ведь у вас есть, верно? ;), подмонтированные сетевые шары и прочее.
Финиш
Всё, списки составлены. Теперь для каждого списка файлов выполняем chown . Напомню, что мы старались полностью сохранить владельца файлов с учётом возможно отличающихся user и group.
cat » $chownlist » | xargs -0 sudo chown $user
cat » $chgrplist » | xargs -0 sudo chown : $group
sudo rm » $chownlist » » $chgrplist » # Не забываем подчистить за собой
Проверка
Напоследок, проверим, не осталось ли где-нибудь файлов с неизвестными UID или GID. Для этого существует два полезных условия find -nouser и find -nogroup . Полезно также уточнить поиск, исключив пресловутые ‘/proc’ и ‘/sys’ из поиска:
Если всё было сделано правильно (и в системе не водилось осиротевших файлов) — команда не должна ничего вывести.
Полный код скрипта
Надеюсь, статья окажется полезной. Рекомендую ближе ознакомиться с синтаксисом этой команды: она ведь намного мощнее чем вы думаете 🙂
Напоследок приведу полный код скрипта для смены UID&GID пользователя и его файлов:
#=== Настройки
user =mysql new_uid = 600 old_uid =$ ( id -u $user ) # имя, новый и старый UID
group =mysql new_gid = 600 old_gid =$ ( id -g $user ) # имя, новый и старый GID
#=== Смена UID & GID
sudo usermod -u $new_uid $user
sudo groupmod -g $new_gid $group
#=== Поиск файлов
chownlist =$ ( tempfile ) chgrplist =$ ( tempfile ) sudo find / \
\ ( \ ( -path «/proc» -or -path «/sys» \ ) -prune \ ) -or \
\ ( \ ( -user $old_uid -fprint0 » $chownlist » \ ) , \ ( -group $old_gid -fprint0 » $chgrplist » \ ) \ )
#=== chown и чистка
cat » $chownlist » | xargs -0 sudo chown $user
cat » $chgrplist » | xargs -0 sudo chown : $group
sudo rm » $chownlist » » $chgrplist «