How to get user name using UID on Android?
I got several UIDs like this:
10022, 10011, 1000 Actually I know the user names of them are u0_a22 , u0_a11 , system . But the question is, how can I get the user name using UIDs? There is no /etc/passwd file at all.
2 Answers 2
I wrote a utility class to get the UID/GID name by hardcoding values from android_filesystem_config.h.
String uid = AndroidFilesystemConfig.getNameForId(1000);
AndroidFilesystemConfig.java
import android.os.Build; import android.util.SparseArray; import java.util.Locale; /** * System Users and Groups for the Android platform as specified in * android_filesystem_config.h.
* * Last updated: April 20th, 2016
* * Note: Some OEMs may have specific UIDs for other system users not in this class.
*/ public class AndroidFilesystemConfig < /* first app user */ private static final int AID_APP = 10000; /* offset for uid ranges for each user */ private static final int AID_USER = 100000; /* start of gids for apps in each user to share */ private static final int AID_SHARED_GID_START = 50000; /* end of gids for apps in each user to share */ private static final int AID_SHARED_GID_END = 59999; private static final SparseArraySYSTEM_IDS = new SparseArray<>(); static < putSystemId(0, "root"); /* traditional unix root user */ putSystemId(1000, "system"); /* system server */ putSystemId(1001, "radio"); /* telephony subsystem, RIL */ putSystemId(1002, "bluetooth"); /* bluetooth subsystem */ putSystemId(1003, "graphics"); /* graphics devices */ putSystemId(1004, "input"); /* input devices */ putSystemId(1005, "audio"); /* audio devices */ putSystemId(1006, "camera"); /* camera devices */ putSystemId(1007, "log"); /* log devices */ putSystemId(1008, "compass"); /* compass device */ putSystemId(1009, "mount"); /* mountd socket */ putSystemId(1010, "wifi"); /* wifi subsystem */ putSystemId(1011, "adb"); /* android debug bridge (adbd) */ putSystemId(1012, "install"); /* group for installing packages */ putSystemId(1013, "media"); /* mediaserver process */ putSystemId(1014, "dhcp"); /* dhcp client */ putSystemId(1015, "sdcard_rw"); /* external storage write access */ putSystemId(1016, "vpn"); /* vpn system */ putSystemId(1017, "keystore"); /* keystore subsystem */ putSystemId(1018, "usb"); /* USB devices */ putSystemId(1019, "drm"); /* DRM server */ putSystemId(1020, "mdnsr"); /* MulticastDNSResponder (service discovery) */ putSystemId(1021, "gps"); /* GPS daemon */ // 1022 is deprecated and not used. putSystemId(1023, "media_rw"); /* internal media storage write access */ putSystemId(1024, "mtp"); /* MTP USB driver access */ // 1025 is deprecated and not used. putSystemId(1026, "drmrpc"); /* group for drm rpc */ putSystemId(1027, "nfc"); /* nfc subsystem */ putSystemId(1028, "sdcard_r"); /* external storage read access */ putSystemId(1029, "clat"); /* clat part of nat464 */ putSystemId(1030, "loop_radio"); /* loop radio devices */ putSystemId(1031, "mediadrm"); /* MediaDrm plugins */ putSystemId(1032, "package_info"); /* access to installed package details */ putSystemId(1033, "sdcard_pics"); /* external storage photos access */ putSystemId(1034, "sdcard_av"); /* external storage audio/video access */ putSystemId(1035, "sdcard_all"); /* access all users external storage */ putSystemId(1036, "logd"); /* log daemon */ putSystemId(1037, "shared_relro"); /* creator of shared GNU RELRO files */ putSystemId(1038, "dbus"); /* dbus-daemon IPC broker process */ putSystemId(1039, "tlsdate"); /* tlsdate unprivileged user */ putSystemId(1040, "mediaex"); /* mediaextractor process */ putSystemId(1041, "audioserver"); /* audioserver process */ putSystemId(1042, "metrics_coll"); /* metrics_collector process */ putSystemId(1043, "metricsd"); /* metricsd process */ putSystemId(1044, "webserv"); /* webservd process */ putSystemId(1045, "debuggerd"); /* debuggerd unprivileged user */ putSystemId(1046, "mediacodec"); /* mediacodec process */ putSystemId(1047, "cameraserver"); /* cameraserver process */ putSystemId(1048, "firewall"); /* firewalld process */ putSystemId(1049, "trunks"); /* trunksd process (TPM daemon) */ putSystemId(1050, "nvram"); /* Access-controlled NVRAM */ putSystemId(1051, "dns"); /* DNS resolution daemon (system: netd) */ putSystemId(1052, "dns_tether"); /* DNS resolution daemon (tether: dnsmasq) */ putSystemId(1053, "webview_zygote"); /* WebView zygote process */ putSystemId(1054, "vehicle_network"); /* Vehicle network service */ putSystemId(1055, "media_audio"); /* GID for audio files on internal media storage */ putSystemId(1056, "media_video"); /* GID for video files on internal media storage */ putSystemId(1057, "media_image"); /* GID for image files on internal media storage */ putSystemId(2000, "shell"); /* adb and debug shell user */ putSystemId(2001, "cache"); /* cache access */ putSystemId(2002, "diag"); /* access to diagnostic resources */ /* The range 2900-2999 is reserved for OEMs */ // The 3000 series are intended for use as supplemental group id's only. They indicate // special Android capabilities that the kernel is aware of. putSystemId(3001, "net_bt_admin"); /* bluetooth: get any socket */ putSystemId(3002, "net_bt"); /* bluetooth: get sco, rfcomm or l2cap sockets */ putSystemId(3003, "inet"); /* can get AF_INET and AF_INET6 sockets */ putSystemId(3004, "net_raw"); /* can get raw INET sockets */ putSystemId(3005, "net_admin"); /* can configure interfaces and routing tables. */ putSystemId(3006, "net_bw_stats"); /* read bandwidth statistics */ putSystemId(3007, "net_bw_acct"); /* change bandwidth statistics accounting */ putSystemId(3008, "net_bt_stack"); /* bluetooth: access config files */ putSystemId(3009, "readproc"); /* Allow /proc read access */ putSystemId(3010, "wakelock"); /* Allow system wakelock read/write access */ /* The range 5000-5999 is also reserved for OEMs. */ putSystemId(9997, "everybody"); /* shared between all apps in the same profile */ putSystemId(9998, "misc"); /* access to misc storage */ putSystemId(9999, "nobody"); >private static void putSystemId(int id, String name) < // Check if the uid exists before adding it so we don't add unsupported ids. if (android.os.Process.getUidForName(name) != id) < // Not valid on this system. Most likely due to a lower API. return; >SYSTEM_IDS.put(id, name); > /** * @return An array of system UIDs */ public static SparseArray getSystemIds() < return SYSTEM_IDS; >/** * Returns the UID/GID name assigned to a particular id, or if there is none. * * @param id * The UID/GID of a process or file * @return the name of the UID/GID or if the id is unrecognized. */ public static String getNameForId(int id) < String name = SYSTEM_IDS.get(id); if (name == null) < if (id >= AID_SHARED_GID_START && id else < int appId = id - AID_APP; int userId = 0; // loop until we get the correct user id. // 100000 is the offset for each user. while (appId >AID_USER) < appId -= AID_USER; userId++; >if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) < // u_a is used on API 17+ for multiple user account support. name = String.format(Locale.ENGLISH, "u%d_a%d", userId, appId); > else < // app_is used below API 17. name = String.format(Locale.ENGLISH, "app_%d", appId); > > > return name; > private AndroidFilesystemConfig() < throw new AssertionError("no instances"); >>
Using Reflection:
Inspired by odexide’s answer, here is some really ugly reflection I wouldn’t advise using that will get the UID/GID name from getpwuid(uid_t):
public static String getNameForUid(int id) < try < Classclazz = Class.forName("libcore.io.Libcore"); Field field = clazz.getDeclaredField("os"); if (!field.isAccessible()) < field.setAccessible(true); >Object os = field.get(null); if (os != null) < Method getpwuid = os.getClass().getMethod("getpwuid", int.class); if (getpwuid != null) < if (!getpwuid.isAccessible()) < getpwuid.setAccessible(true); >Object passwd = getpwuid.invoke(os, id); if (passwd != null) < Field pw_name = passwd.getClass().getDeclaredField("pw_name"); if (!pw_name.isAccessible()) < pw_name.setAccessible(true); >return (String) pw_name.get(passwd); > > > > catch (Exception ignored) < >return null; >
How can I look up a username by id in linux?
Is there a command to lookup up a username from a uid ? I realize this can be done by looking at the /etc/passwd file but I’m asking if there is an existing command to to this, especially if the user executing it is not root. I’m not looking for the current user’s username, i.e. I am not looking for whoami or logname . This also made me wonder if on shared web hosting this is a security feature, or am I just not understanding something correctly? For examination, the /etc/passwd file from a shared web host:
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin news:x:9:13:news:/etc/news: uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin nscd:x:28:28:NSCD Daemon:/:/sbin/nologin vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin pcap:x:77:77::/var/arpwatch:/sbin/nologin rpc:x:32:32:Portmapper RPC user:/:/sbin/nologin mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin oprofile:x:16:16:Special user account to be used by OProfile:/home/oprofile:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin avahi:x:70:70:Avahi daemon:/:/sbin/nologin rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin haldaemon:x:68:68:HAL daemon:/:/sbin/nologin xfs:x:43:43:X Font Server:/etc/X11/fs:/sbin/nologin avahi-autoipd:x:100:104:avahi-autoipd:/var/lib/avahi-autoipd:/sbin/nologin named:x:25:25:Named:/var/named:/sbin/nologin mailman:x:32006:32006::/usr/local/cpanel/3rdparty/mailman/mailman:/usr/local/cpanel/bin/noshell dovecot:x:97:97:dovecot:/usr/libexec/dovecot:/sbin/nologin mysql:x:101:105:MySQL server:/var/lib/mysql:/bin/bash cpaneleximfilter:x:32007:32009::/var/cpanel/userhomes/cpaneleximfilter:/usr/local/cpanel/bin/noshell nagios:x:102:106:nagios:/var/log/nagios:/bin/sh ntp:x:38:38::/etc/ntp:/sbin/nologin myuser:x:1747:1744::/home/myuser:/usr/local/cpanel/bin/jailshell
drwx------ 3 root root 1024 Apr 16 02:09 spamd-22217-init/ drwxr-xr-x 2 665 664 1024 Apr 4 00:05 update-cache-44068ab4/ drwxr-xr-x 4 665 664 1024 Apr 17 15:17 update-extraction-44068ab4/ -rw-rw-r-- 1 665 664 43801 Apr 17 15:17 variable.zip -rw-r--r-- 1 684 683 4396 Apr 17 07:01 wsdl-13fb96428c0685474db6b425a1d9baec
We can see root is the owner of some files, and root is also showing up in /etc/passwd , however the other users/groups all show up as numbers.
How do I get the current user’s username in Bash?
It seems none of the methods proposed so far work without relying on $USER or invoking a separate process. Is there no bash builtin to get the username without invoking a separate process?
When you’ve heard a command but aren’t sure how to use it, checking man whoami is usually a good first stop to check for documentation.
14 Answers 14
On the command line, enter
Just a quick note that $USER and whoami return different values if your running a command through ssh as another user. whoami returns the OS user and $USER returns the ssh user.
In some cases, $USER is not set at all. Worse, it is just an environment variable, so it can be overridden by the user: USER=thisisnotmyname bash -c ‘echo $USER’ # prints thisisnotmyname
@SethMMorton I realise I made the issue sound worse than it usually is. To answer the question, though, using whoami (as you suggested) eliminates the problem altogether, assuming overridden environment variables is a potential issue in your context.
«current username» is slightly ambiguous. What do you want to get when running under sudo? «echo $USER» produces the name I logged in as whether run under sudo or not, while «whoami» returns «root» when run under sudo and my actual login name otherwise. Scripts that need to be run as sudo are more likely to be in that minority of scripts that have need of your login name rather than «root».
An alternative to whoami is id -u -n .
id -u will return the user id (e.g. 0 for root).
Unless I’m mistaken this would be the way to go if portability is a concern as the id command and -u and -n flags are a part of posix
This really should be the accepted answer. «$
if you tried the command before adding untrue comments, you would see that the -n argument prints the username, just like the original question asked. see the following: id -u -n prints brett — even on darwin.
A great alternative when checking on live container instances with very few command line apps installed. whoami isn’t installed on many of the lite images out there.
Use the standard Unix/Linux/BSD/MacOS command logname to retrieve the logged in user. This ignores the environment as well as sudo, as these are unreliable reporters. It will always print the logged in user’s name and then exit. This command has been around since about 1981.
My-Mac:~ devin$ logname devin My-Mac:~ devin$ sudo logname Password: devin My-Mac:~ devin$ sudo su - My-Mac:~ root# logname devin My-Mac:~ root# echo $USER root
This was particularly helpful to me over whoami or $USER as I am using sudo to execute as another user, but want the original user not the sudo user.
BTW this is the best answer, not only for me personally but also to the purpose of the OP’s question.
A hack the I’ve used on Solaris 9 and Linux and which works fine for both of them:
This snippet prints the name of the user with the current EUID.
NOTE: you need Bash as the interpreter here.
On Solaris you have problems with methods, described above:
- id does not accept the -u and -n parameters (so you will have to parse the output)
- whoami does not exist (by default)
- who am I prints owner of current terminal (ignores EUID)
- $USER variable is set correctly only after reading profile files (for example, /etc/profile )
Why do you need bash as the interpreter? Nothing in the command line shown seems to be specific to any shell. In fact, why even include the pipe through awk? As far as I can tell, your ps command is everything required to display the owner of the current shell’s pid.
For us as humans to disregard the superfluous information is natural. The awk portion isolates the desired data— for variables or in general the computer that can’t make on the fly assumptions just yet at this rudimentary level.
On Solaris, use command -p id (from a POSIX shell) or /usr/xpg4/bin/id . More generally, on Solaris, you’d want to modify your environment to put yourself in a POSIX environment (with something like PATH= getconf PATH` and be sure to run /usr/xpg4/bin/sh ) to avoid being stuck with commands from the 70s/80s.
- id prints the user id along with the groups. Format: uid=usernumber(username) .
- whoami gives the current user name
$whoami isn’t available as a variable in bash. You need to do either $(whoami), or `whoami` to actually execute the whoami command!
When root (sudo) permissions are required, which is usually 90%+ when using scripts, the methods in previous answers always give you root as the answer.
To get the current «logged in» user is just as simple, but it requires accessing different variables: $SUDO_UID and $SUDO_USER .
echo $SUDO_UID echo $SUDO_USER
myuid=$SUDO_UID myuname=$SUDO_USER
In Solaris OS I used this command:
$ who am i # Remember to use it with space.
On Linux- Someone already answered this in comments.
Those 2 commands display 2 different informations. Just log as root, use «su — xxx», and see for yourself.
. gets you the regular user (if non-sudo) → or ← the regular user behind the current sudo call.
How could i do it in nested quotes? e.g. my_var=»$(‘/some/path/to/$
The current user’s username can be gotten in pure Bash with the $ parameter expansion (introduced in Bash 4.4):
The : built-in (synonym of true ) is used instead of a temporary variable by setting the last argument, which is stored in $_ . We then expand it ( \u ) as if it were a prompt string with the P operator.
This is better than using $USER , as $USER is just a regular environmental variable; it can be modified, unset, etc. Even if it isn’t intentionally tampered with, a common case where it’s still incorrect is when the user is switched without starting a login shell ( su ‘s default).