Stray processes after a user logout

I tried this on a couple of the machines updated to Mac OS X 10.9.4. I log in as a particular user, let's say user1, and then log out, and login as another user, let's say user2. After inspecting the system processes, I find a bunch of processes running on behalf of user1 and these don't seem to want to terminate:

/sbin/launchd

/usr/sbin/distnoted agent

/usr/sbin/cfprefsd agent

/usr/libexec/xpcd

/System/Library/PrivateFrameworks/TCC.framework/Resources/tccd

com.apple.IconServicesAgent

com.apple.imdpersistence.IMDPersistenceAgent

/usr/libexec/secd

/System/Library/Frameworks/Security.framework/Versions/A/Resources/CloudKeychain Proxy.bundle/Contents/MacOS/CloudKeychainProxy

com.apple.NotesMigratorService

com.apple.InputMethodKit.UserDictionary

/System/Library/PrivateFrameworks/CloudServices.framework/Resources/com.apple.sb d

com.apple.DataDetectorsDynamicData

/System/Library/PrivateFrameworks/SyncedDefaults.framework/Support/syncdefaultsd

com.apple.iCloudHelper


Can anybody help me to find decent documentation about these processes and if I can disable or safely terminate as many of them as possible? I didn't manage to find anything useful in the man pages or searching with google. I haven't observed such a behavior with OS X 10.7 and older versions.

OS X Mavericks (10.9.4)

Posted on Jul 27, 2014 7:20 PM

Reply
Question marked as Top-ranking reply

Posted on Sep 4, 2014 1:05 AM

I gave it a try. I created a script that can be installed as a cron job and I will paste it at the end of the post. You can try to use it at your own risk.


Mini manual: The script will kill all the stray processes for a particular user on a machine, the user has logged out. Additionally the script would not kill the user processes in case it detects presence of a optional specified file in the command line (helpful if the user has automated processes). I'd recommend it to execute it periodically as a root user, in its crontab for example. Executing the script without command line arguments will result in a display of its usage.


Installation (ask a technical person if unsure): Copy the script source below and paste it in some script file, say as /usr/local/bin/kill_stray_processes, then give it executable rights. From the terminal it would look like something similar:

# Create /usr/local/bin in case it doesn't exist

sudo mkdir -p /usr/local/bin

# Use your favourite editor to paste the source of the script, here for example vi

sudo vi /usr/local/bin/kill_stray_processes

# After pasting the source, saving and closing the editor, set executable rights of the script

sudo chmod a+x /usr/local/bin/kill_stray_processes


The cron job to check and kill stray processes for user myuser every hour would look like this:

0 * * * * /usr/local/bin/kill_stray_processes myuser


Suppose an automated process creates temporarily a file /tmp/mylock and you don't want to kill processes at the time it runs. The cron job would look like this:

0 * * * * /usr/local/bin/kill_stray_processes myuser /tmp/mylock


The source of the script starts below (no empty line in the beginning):

#!/bin/bash

# SYNOPSIS:

# This is a command line utility that would kill processes belonging

# to a particular user which does not have login session. Additionally

# the script can take as a command line argument files which when present

# can cause it not to proceed with killing the stray processes.

#

# USAGE:

# kill_stray_user_processes <user> [<lock_file>...]

#

COMMAND=$0

COMMAND_PATH=`dirname $COMMAND`

pushd . > /dev/null

cd $COMMAND_PATH

COMMAND_PATH=`pwd`

COMMAND_NAME=`basename $0`

popd > /dev/null

#

USER="$1"

if [ -z "$USER" ]; then

echo "USAGE: $COMMAND_NAME <user> [<lock_file>...]"

exit 0

fi

shift 1

# In case of specified lock files check for their presence and exit if any

while [ -n "$1" ]; do

if [ -f "$1" ]; then

exit 0

fi

shift 1

done

# Make sure the user has logged out

if w | grep -q -i "^${USER}[[:space:]]"; then

exit 0

fi

# Kill the stray launchd's and all their subprocesses

for pid in `ps -jaxwww | grep -i "^${USER}[[:space:]]" | grep "/sbin/launchd" | awk '{print $2}'`; do

bash -c "kill -- -${pid}"

done

# Try to kill gracefully everything else

for pid in `ps -jaxwww | grep -i "^${USER}[[:space:]]" | awk '{print $2}'`; do

bash -c "kill -- -${pid}" 2> /dev/null

done

# Kill forcefully everything that has left

for pid in `ps -jaxwww | grep -i "^${USER}[[:space:]]" | awk '{print $2}'`; do

kill -9 $pid 2> /dev/null

done

28 replies
Question marked as Top-ranking reply

Sep 4, 2014 1:05 AM in response to colbruA

I gave it a try. I created a script that can be installed as a cron job and I will paste it at the end of the post. You can try to use it at your own risk.


Mini manual: The script will kill all the stray processes for a particular user on a machine, the user has logged out. Additionally the script would not kill the user processes in case it detects presence of a optional specified file in the command line (helpful if the user has automated processes). I'd recommend it to execute it periodically as a root user, in its crontab for example. Executing the script without command line arguments will result in a display of its usage.


Installation (ask a technical person if unsure): Copy the script source below and paste it in some script file, say as /usr/local/bin/kill_stray_processes, then give it executable rights. From the terminal it would look like something similar:

# Create /usr/local/bin in case it doesn't exist

sudo mkdir -p /usr/local/bin

# Use your favourite editor to paste the source of the script, here for example vi

sudo vi /usr/local/bin/kill_stray_processes

# After pasting the source, saving and closing the editor, set executable rights of the script

sudo chmod a+x /usr/local/bin/kill_stray_processes


The cron job to check and kill stray processes for user myuser every hour would look like this:

0 * * * * /usr/local/bin/kill_stray_processes myuser


Suppose an automated process creates temporarily a file /tmp/mylock and you don't want to kill processes at the time it runs. The cron job would look like this:

0 * * * * /usr/local/bin/kill_stray_processes myuser /tmp/mylock


The source of the script starts below (no empty line in the beginning):

#!/bin/bash

# SYNOPSIS:

# This is a command line utility that would kill processes belonging

# to a particular user which does not have login session. Additionally

# the script can take as a command line argument files which when present

# can cause it not to proceed with killing the stray processes.

#

# USAGE:

# kill_stray_user_processes <user> [<lock_file>...]

#

COMMAND=$0

COMMAND_PATH=`dirname $COMMAND`

pushd . > /dev/null

cd $COMMAND_PATH

COMMAND_PATH=`pwd`

COMMAND_NAME=`basename $0`

popd > /dev/null

#

USER="$1"

if [ -z "$USER" ]; then

echo "USAGE: $COMMAND_NAME <user> [<lock_file>...]"

exit 0

fi

shift 1

# In case of specified lock files check for their presence and exit if any

while [ -n "$1" ]; do

if [ -f "$1" ]; then

exit 0

fi

shift 1

done

# Make sure the user has logged out

if w | grep -q -i "^${USER}[[:space:]]"; then

exit 0

fi

# Kill the stray launchd's and all their subprocesses

for pid in `ps -jaxwww | grep -i "^${USER}[[:space:]]" | grep "/sbin/launchd" | awk '{print $2}'`; do

bash -c "kill -- -${pid}"

done

# Try to kill gracefully everything else

for pid in `ps -jaxwww | grep -i "^${USER}[[:space:]]" | awk '{print $2}'`; do

bash -c "kill -- -${pid}" 2> /dev/null

done

# Kill forcefully everything that has left

for pid in `ps -jaxwww | grep -i "^${USER}[[:space:]]" | awk '{print $2}'`; do

kill -9 $pid 2> /dev/null

done

Oct 14, 2014 7:26 AM in response to Georgy Karageogiev

I'm having the same problem in the public labs I manage running Mavericks (Yosemite has the same issue, BTW). I tried modifying Georgy's script to run as a login hook but I never could get this approach to work reliably. For starters, if the script kills the user's loginwindow process, it will self-terminate (along with most other user processes) before it's finished, possibly leaving you worse off than before. It's relatively trivial to modify the script to not do this, but I still couldn't get it to behave consistently, probably due to timing issues.


In our environment, we use AD logins, but not roaming homedirs. Homedirs are created at login and periodically cleaned. Because of this, we can simply look at the contents of the /Users directory to determine which users might need to be terminated. The following script won't win any awards for efficiency, but it gets the job done. The script will skip users who are actually logged in when it executes. I can run this manually via ARD (hence the ech statements), but also have it set up as a launchdaemon to run periodically.


I still end up with cfprefsd processes for old users, but this is because something is relaunching them after they are killed (probably the "system" cprefsd instance).



#!/bin/bash

for DIR in $(ls /Users); do

if [ $DIR != 'Shared' -a $DIR != '.localized' ]; then

SKIP="no";

for USER in $(users); do

if [ $DIR == $USER ]; then

SKIP="yes";

fi;

done;

if [[ $SKIP = "yes" ]]; then

echo "User $USER is actually logged in"

else

pkill -9 -u $DIR;

echo "User $DIR has been staked";

fi;

fi;

done;

Aug 16, 2014 4:58 AM in response to micahwkb

I didn't find any reasonable documentation, but I did some experiments.


If you run the Activity Monitor app or some utility in the terminal (I built myself and used pstree), you can see the hierarchy of the processes:

|-+= <process_id_0> user1 /sbin/launchd

| |--= <process_id_1> user1 /usr/sbin/distnoted agent

| |--= <process_id_2> user1 /usr/sbin/cfprefsd agent

| |--= <process_id_3> user1 /System/Library/PrivateFrameworks/TCC.framework/Resources/tccd

| |--= <process_id_4> user1 /usr/libexec/secd

| |--= <process_id_5> user1 /System/Library/Frameworks/Security.framework/Versions/A/Resources/CloudKeychai nProxy.bundle/Contents/MacOS/CloudKeychainProxy

| \--= <process_id_6> user1 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework /Versions/A/Support/mdflagwriter

|--= <process_id_7> user1 /usr/libexec/xpcd

|--= <process_id_8> user1 com.apple.IconServicesAgent

|--= <process_id_9> user1 com.apple.imdpersistence.IMDPersistenceAgent


Here <process_id_n> represents a number, the ID of the corresponding process. It turned out that I can kill the whole process tree started by the launchd for this particular user, as a superuser. The command from the terminal I used (note the '-' before the process ID of the launchd):

sudo kill -- -<process_id_0>


Then a couple of processes left, that don't belong to this tree that apparently have started separately:

|--= <process_id_7> user1 /usr/libexec/xpcd

|--= <process_id_8> user1 com.apple.IconServicesAgent

|--= <process_id_9> user1 com.apple.imdpersistence.IMDPersistenceAgent

An ordinary kill didn't stop these. I had to use the

KILL
signal
:

sudo kill -

KILL
<process_id_7> <process_id_8> <process_id_9>

Now I cannot guarantee 100% that we can safely use this approach to stop the stray user processes without corrupting files, because we cannot find documentation, BUT something like this has to happen automatically when you shut the computer down. So you can try it at your own risk (and please share your experience).


Still waiting for a better solution or explanation from Apple.

Oct 2, 2014 8:23 AM in response to Georgy Karageogiev

I'll check your script again. I just made a little script to run


sudo pkill -9 -fx com.IconServicesAgent


and at least that seems to be working. I figured since that is the largest process and taking up the most memory, that may be enough to fix the issue of machines becoming unresponsive. I will test your script in the way you suggested here in a bit.

Oct 22, 2015 2:32 PM in response to Georgy Karageogiev

I'm using this to manually kill the zombie user processes in El Capitan:


function kill_zombie () {

ZOMBIE_USER=sam

PROCS=$(ps -u $ZOMBIE_USER | awk '/[0-9]/ {print $2}')

echo "Active processes for $ZOMBIE_USER: $($PROCS | wc -l)"

for P in ${PROCS[@]};do

printf " $P: ";

sudo kill -kill $P && echo " - OK";

done

echo "Remaining:"

ps -u $ZOMBIE_USER | awk '/[0-9]/ {print $2}'

}

Oct 14, 2014 8:12 AM in response to JKersten

I was going nuts over this issue. Apple returned the bug submission with the reply:

"XPC services will only be killed if the system needs to reclaim the resources for some other process."

Which is obviously not happening, because the process are crashing my computers. I washed my hands of it and downgraded them to Mountain Lion. Everything is back to working properly now. I didn't want to downgrade, particularly because of SMB2 incompatibilities of pre-Mavericks OSes. But I am done caring about this issue for now.

Sep 5, 2014 1:11 AM in response to colbruA

You can ignore name mismatch in the script comment, excuses for the confusion. You can name the script as you wish. If you want to use the script without modifying it, you have to schedule automated jobs as root for every user you want to check. Example in the root crontab considering the usage above:

0 * * * * /usr/local/bin/kill_stray_processes user1

0 * * * * /usr/local/bin/kill_stray_processes user2 /tmp/lock2

0 * * * * /usr/local/bin/kill_stray_processes user3

Jul 28, 2014 1:57 PM in response to Eric Root

I am helping with the administration of a couple of mac machines, laptops and servers. I have some concerns:

  • Security: the stray processes may cache sensitive information in the time the user has logged out. The owners of the laptops wouldn't like such a situation.
  • Performance: I can't judge the impact of such processes on the performance currently, but I want to keep the running environments as simple as possible, especially on server machines.
  • Battery life
  • You guessed it right, I want simpler logs.

Also the insufficient or completely missing documentation about these processes amplifies my concerns.

Sep 4, 2014 12:19 AM in response to Georgy Karageogiev

I'd like to give this one a bump.


I too have noticed this problem.


My Network Home users suffer from randomly corrupted local keychain. The symtoms are Mail is not able to receive or send emails because the password can't be stored in the keychan. And we have random freezing of systems when using Word 2011.

This might be related to the processes of prior users not being terminated.


Was someone able to write a daemon to terminate the stray processes automatically?


I have found the following https://github.com/mkuron/mountclean-osxbut was not able to make it work.

May I ask the coders in this thread for help?!


Thanks

Sep 4, 2014 9:52 PM in response to Georgy Karageogiev

Thank you Georgy


As you state the usage is as followed:

# USAGE:

# kill_stray_user_processes <user> [<lock_file>...]


Since there are different users using the computer how do I do that?

your script relys on the external input of <user> to kill the correct processes.

To take into account the ever changing users I somehow need $USER to input into the script.

But if we run the script as root will $USER not return root and this will kill root processes?

Sep 5, 2014 2:18 AM in response to colbruA

The script served my case because I had not that many users per computer to deal with. You can reuse parts of it in a script that would cover your needs. I wouldn't recommend trying this for all the users on a machine, because the operating system has own designated users that run various processes. And last but not least, I'd expect that Apple will eventually address this issue. Hope this helps.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Stray processes after a user logout

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.