dscl Command Breaks Login - bash

I am trying to change the user image for the photo account using these dscl commands:
sudo dscl . delete /Users/photo Picture
sudo dscl . delete /Users/photo JPEGPhoto
sudo dscl . create /Users/photo Picture "/Library/User Pictures/Halloween.psd"
sudo dscl . create /Users/photo JPEGPhoto "/Library/User Pictures/Halloween.psd"
After that I clear caches and kill cfprefsd like so:
sudo killall cfprefsd
sudo kextcache -system-caches
I have run this without killing/clearing, with the same result, which is...
After running these commands, when I logout a pinwheel appears on a black background I can still see my cursor, but then the monitor goes black and there is no cursor.
This repeats until a hard shutdown is done. It is impossible to log back in even after rebooting because I can never get to the login screen.
I tried copying off the vanilla loginwindow prefs file and replacing it after the login screen is screwed up. I tried to boot to safe mode but a normal boot appears to occur. When I boot in verbose mode it gets to the same point before login. Only while booting in verbose mode the screen flickers with the login background but then goes back to the loop, which appears to be executing more code (it looks irrelevant, like Wi-Fi settings etc.)
Information on the machines is irrelevant so I don't need to backup or restore the machine as a part of my solution.
Edit:
I have now come to the revelation that...
sudo dscl . create /Users/photo Picture "/Library/User Pictures/Halloween.psd"
Doesn't do anything. After running the command, I read back the property and it's still there. Any ideas?
Edit 2:
The solution to anyone else who is facing this issue is to add:
sudo dscl . -read /Users/photo JPEGPhoto
after deleting the JPEGPhoto key, and it works perfectly!

The JPEGPhoto attribute shouldn't be a file path, it needs to be a hexidecimal-encoded JPEG image. Take a look at the JPEGPhoto attribute for another account to get an idea what it should look like.

Related

Changing user in bash script

I wanted to create an installation script for my raspberry pi which secures the default installation by configuring/hardening ssh, installing a firewall and fail2ban and finally to get rid off the default user of Raspbian. All other parts work but the final part always shows me an error.
The new user is created and added to the sudo group. After that I want to delete the old user 'pi'. As the script runs with sudo in the user context of 'pi' I thought I could solve this by switching to 'su' but I just get an error that the user couldn't be deleted as it is used by a process:
echo "Enter the new user name? Only lower case letters allowed!"
read user
sudo adduser $user && adduser $user sudo
echo "default user 'pi' will now be deleted"
su -c "deluser -remove-home pi"
If I check with 'users' the user 'pi' is gone but I can still log in with this account. How can I solve this problem inside the script?
I tried the answers I found here: How do I use su to execute the rest of the bash script as that user? and here: https://unix.stackexchange.com/questions/361327/how-to-login-as-different-user-inside-shell-script-and-execute-a-set-of-commands but nothing seem to work. I searched Google but I can't find any solution that works. Is it even possible what I'm trying to?
I usually add set -eux at the beginning of the bash script. This allows to debug and find typos and errors.
Try to switch user inside the script with
sudo -i -u ${user} $(command to delete pi here)
Think i found the cause of the problem. 'set -eux' was a great help:
deluser pi
Removing user `pi' ...
Warning: group `pi' has no more members.
userdel: user pi is currently used by process 445
/usr/sbin/deluser: `/usr/sbin/userdel pi' returned error code 8. Exiting.
I tried ps -fu pi to find the process which causes the trouble: it's /lib/systemd/systemd --user Is there a way to stop this process inside the script?

Why do I have two users with uid 0 on my Mac?

When I execute following code in terminal:
dscl . -list /Users UniqueID
The output shows two users with uid 0: one named root, the other named newuser.
But when I execute:
cat /etc/passwd
There is only one user with uid 0, i.e. root.
I want to know why the answers of above commands are different, and how I can delete the newuser.
I am using the newest version of Mac OS X.
I found this question when I failed to install parallels desktop trial edition. The error message is:
Cannot install Parallels Desktop because there is a non-root user account with the UID 0 in your system (http://kb.parallels.com/cn/122763)
I've already called apple support for help, but they had no solution.
Update:
It seems that newuser runs the processes which root should run. Furthermore, the ps command is also run by newuser, but my user name is xlnwel
What on earth is this newuser?
Update 2:
I have no idea what I have done yesterday (maybe just reboot the computer), but today these processes are run by root. but there are still two users with 0 when I run:
dscl . -list /Users UniqueID
Interesting.
There is no strict 1-1 mapping from user name to user id in most of *NIX systems, so technically it's all fine to have a few user names with same UID. The reason why you don't see it in /etc/passwd is that the file is used for legacy accounts, and directory services are expected to be the source of truth.
I guess you never created the newuser? You must understand that the user is effectively a root backdoor into your system, as anyone having the password can act as UID 0 and have full access to your machine.
I'd check for existence of "newuser" in Users & Groups preference pane. You surely should be able to just remove it with sudo /usr/bin/dscl . -delete "/Users/newuser". The important part is to figure how that user got into your machine in the first place.
Immediate solution: remove the user using the command above.
Actual fix: reinstall the machine clean and restore your data from backups.
I will answer your questions in turn:
1. "... why the answers of above commands are different?"
The reason the answers from the two commands are different is because they are looking at two different records sets.
The /etc/passwd file is only used by OSX in single user mode, as pointed out at the top of the file:
##
# User Database
#
# Note that this file is consulted directly only when the system is running
# in single-user mode. At other times this information is provided by
# Open Directory.
#
# See the opendirectoryd(8) man page for additional information about
# Open Directory.
##
As Directory Services is used for users and resources (printers, servers) you will most likely have more entries in a Directory Services listing than the number of entries in /etc/passwd file.
2. "... how I can delete the new user?"
To delete the user you can use dscl commands as pointed out by Farcaller above:
a) check the details for the user and group with:
dscacheutil -q user
And then:
dscacheutil -q group
I would also check to see what other users are in the same group that "newuser" is in, what files are in /Users/newuser, and then make decisions based on that information.
b) If all looks OK, delete the user with:
sudo dscl . delete /Users/newuser
This will delete everything under the specified directory. If you want to remove the user's home directory you will need to do this manually with:
rm -rf /Users/newuser
If the "newuser" was in its own group, I would also look at deleting the group with:
sudo dscl . delete /Groups/<<GROUP_NAME_OF_NEWUSER_FROM_A_ABOVE>>
Hope that helps.
I have a solution that helped me
Check list of IDs
dscl . -list /Users UniqueID
change the UID to a not used number with the phrase:
sudo dscl . -change /Users/newuser UniqueID 0 599
where 599 is unique ID and "newuser" is a second user with 0

Create user for running a daemon, on MacOS X?

What is the right way to create a user on MacOS X, from the command line, which will be used only for running a sever application? For example, there is already the '_www' user for Apache httpd, but for the new application I want it to be using its own account.
There is no "adduser" command. The Mac approach is to use the dscl command, which is the "Directory Service Command Line Utility". Directory Services is similar in notion to LDAP, but is a different solution.
The examples below will use 'mydaemon' as the intended account, though typically you would use a value matching the name of your daemon application.
All daemon users are prefixed with an underscore, such as _www.
To list the attributes on an existing entry:
sudo dscl . -read /Users/_www
Before creating a user, create a group choosing an unused group id (here we chose 300):
sudo dscl . -create /Groups/_mydaemon
sudo dscl . -create /Groups/_mydaemon PrimaryGroupID 300
Once done, we create a new user (we use the same id as we did for the group, that won't be using a shell:
sudo dscl . -create /Users/_mydaemon UniqueID 300
sudo dscl . -create /Users/_mydaemon PrimaryGroupID 300
sudo dscl . -create /Users/_mydaemon UserShell /usr/bin/false
The above is based on reading up on various information sources and verifying the process myself. One reference, that I found useful is:
http://minecraft.gamepedia.com/Tutorials/Create_a_Mac_OS_X_startup_daemon
Note, there is also GUI version of dscl (location based on MacOS X 10.10):
/System/Library/CoreServices/Applications/Directory\ Utility.app/

How to use Terminal, launched from OSX setup screen, to create new user?

I need to create a new user account on a system drive (10.10.1) because I am unable to log in to the only existing one. I can however get into the OSX setup from a prepared USB flash drive, and launch Terminal there.
I guess it would be possible to add the user account "testuser" with the following method:
dscl . create /Users/testuser
dscl . create /Users/testuser UserShell /bin/bash
dscl . create /Users/testuser RealName "Test User"
dscl . create /Users/testuser UniqueID 503
dscl . create /Users/testuser PrimaryGroupID 1000
dscl . create /Users/testuser NFSHomeDirectory /Local/Users/testuser
dscl . passwd /Users/testuser PASSWORD
dscl . append /Groups/admin GroupMembership testuser
Now entering
-bash-3.2# dscl . create /Users/testuser
what I get from Terminal is this:
-bash: dscl: command not found
I am not the most experienced with command line tools, and am clueless on how to get it to work.
Any help is greatly appreciated.
I'm not sure how you prepared the USB drive, but it looks like it doesn't include dscl. You can use the copy of dscl from the regular startup volume, but it'd still be trying to create a user on the USB disk. To fix that, you'd need to use dscl's -f option to point it to the user database you actually wanted to edit (see here for something similar).
"/Volumes/Macintosh HD/usr/bin/dscl" -f "/Volumes/Macintosh HD/var/db/dslocal/nodes/Default" localonly -create /Local/Target/Users/testuser
...etc. But even then, I'm not sure it'll handle setting the user's password correctly (there used to be a bug relating to that, but I think it got fixed).
There's a much easier way. Just delete the file /var/db/.AppleSetupDone from your regular volume (not the USB disk):
rm "/Volumes/Macintosh HD/var/db/.AppleSetupDone"
... then reboot normally and it'll run through the Setup Assistant, including letting you create a new admin account (note that existing accounts will be preserved). You can use the new admin to clean up whatever needs to be fixed (reset PW on old admin account?), then delete it when everything is back to normal.

Running script with admin permissions on OS X

I've tried my best to find out a solution with the many script questions on Stack Overflow and the internet, but I can't seem to find the solution I need.
What I want to do is create a more automated and less clicking solution to remove all the Mobile cached user accounts on a system. I've been logging in and manually going to user accounts and removing the users one at a time by clicking the "-" button, then clicking "Delete Immediately" for the user data. This works, but is time consuming and I have better things to do with my time. So I knew there had to be a way to do this with a script.
I ran across this code:
for cuser in `dscl . -list /Users AuthenticationAuthority | grep LocalCachedUser | awk '{print $1}' | tr '/n' ' '`; do
dscl . -delete /Users/$cuser
done
If I run this in terminal I get permission errors. So I figured I need to run it with sudo. So I started looking into creating AppleScripts to run the script, but I can't seem to find the right way to do it.
Any ideas? By the way, I'm new to scripting on the Mac, so please comment your code so I know whats happening, and so I don't just run some script code without know what it'll do. :)
Thanks
To perform a shell script with sudo or administrator privileges append with administrator privileges to the end of your do shell script line. For example:
do shell script "/path/to/script/file.sh" user name "adminusershortname" password "password" with administrator privileges
You can find more on Apple's technote dealing with do shell script
That said, saving this as a shell script and running the shell script using sudo would work just as well.
#! /bin/sh
for cuser in `/usr/bin/dscl . -list /Users AuthenticationAuthority | grep LocalCachedUser | awk '{print $1}' | tr '/n' ' '`; do
/usr/bin/dscl . -delete /Users/$cuser
done
Save it as say removeUser.sh, use chmod to set it as executable (chmod 755) and then run it (sudo ./removeUser.sh)
You can do this by editing your system's sudoers file. This will allow the account you use to run this script (via cron, etc.) the ability to run sudo without a password.
To edit the sudoers file you use visudo, but it must be run with admin permission. Try:
$ sudo visudo
Add a line like the following to the end of the file, replacing user_name with the user who will run your script. Note, use tabs between each field.
user_name ALL=(ALL) NOPASSWD:ALL
Now user_name should be able to type sudo and will not be prompted for a password.
Also note that visudo is a text editor that mirrors the vi editor and uses the same commands as vi.
I don't have a mac handy so I can't verify if this would work.
Try running
su -
Then running your script. If that works, try
crontab -e
and adding an entry to run that script of yours.
Are you familiar with crontab? well if not google it if need be.
But basically to run it every day at midnight you'd have something like
0 * * * * /path/to/script
See: http://en.wikipedia.org/wiki/Cron

Resources