Articles April 17, 2007 at 4:39 pm

Automatically disconnecting disabled/asleep AFP sessions.

So a few people on the macos-x-server mailing list noticed that recent versions of OS X Server seem to be building up large numbers of Disabled/Asleep connections on their AFP servers, even with appropriate disconnection settings when users don't have files open.

 I'm even seeing this for servers where AFP session caching has been disabled, and this is as good a time as any to again point readers towards Apple's article on Understanding the "disconnect when idle" feature for AFP connections.

 I've been doing a little bit of work lately on scripts that parse out the result of serveradmin commands, so I thought I'd post up a script I put together that illustrates how you can do this with PHP command line scripting.  

Read on to download the script and read a brief description of how it works. 

Basically the script works like this:

  1. Issue the serveradmin command 'getConnectedUsers' to the AFP service to build up an array of all current AFP sessions
  2. Check each session, and build up an array of all current disabled/asleep sessions
  3. Check each disabled/asleep session and build up an array of all that have been idle over a certain period of time
  4. Issue the serveradmin command 'disconnectUsers' to the AFP service for each such session
  5. Print the username and IP to the screen of each disconnected session

 

There are really only four parameters to configure at the start of the script, and hopefully the in-line comments as shown below explain how they work.

// The disconection threshold sets the idle time threshold for disconnections.<br />// Any connection that has been idle for a time greater than this will be disconnected.<br />// This is in seconds, so for one hour, set it to 3600, 24 hours, set it to 86400, etc.<br /><br />&#36;disconnection_threshold = 86400;<br /><br />// The disconnection message sets the message that users will be sent when being disocnnected.<br />// Leave it empty to not send a message.<br /><br />&#36;disconnection_message = &quot;&quot;;<br /><br />// The disconnection time sets the amount of time users will be given before being disconnected.<br />// Leave it at 0 to disconnect immediately.<br /><br />&#36;disconnection_time = 0;
&nbsp;// The report_disconnection_details flag sets whether this script reports the details of disconnected sessions<br />// when finished. You probably want to set this to 0 if you&#39;re scheduling the script.<br /><br />&#36;report_disconnection_details = 1;

 

After finishing this script I realised that a better general framework may have been to use the -xml output option of serveradmin instead, and then use an XML parser to pull out the info, but in this simple case it's easy enough to use preg_replace to pull out the relevant data.

 

When you download the script, make sure the permissions are such that it is executable, and then you should be able to simply run it from the command line on your AFP server. It's probably a good idea to open up the GUI of Server Admin to examine your current connections, and then refresh the display after executing the script, just to make sure things are working happily for you.

 As always, if you follow this link to download the script and run it without testing it out, it may do anything, up to and including anything as disastrous as Australia not actually crushing all their opposition in the ICC Cricket World Cup 2007 or new episodes of Heroes being delayed by another couple of months….

No Comments

  • I don’t have definitive proof, but in the past I’ve definitely seen a correlation between large numbers of stale connections and AFP service slow downs, even when active connections aren’t consuming much in the way of AFP resources.

    But hey, correlation != causation.

    I was hoping that this script illustrates how Apple have actually given us quite good tools for extracting service data and how you can mine that data to perform certain actions.

    You could easily extend this script to do other things like:

    • Emulate different disconnection timeouts for different network locations. You might have your local LAN users stay connected permanently, but run this script regularly to disconnect remote users after a certain period of time, with a disconnection time and disconnection message.
    • Along the same lines you could set up different behaviours for different classes of users, by perhaps examining their group membership or looking for keywords in the user record.
    • You can use the command ‘getHistory’ on the AFP service to retrieve info about the number of connections and the throughput, and say write a script to disconnect the most idle users after the total number of connections or throughput hits a certain threshold.

    Unfortunately you can’t see a list of all possible service commands from the man page for serveradmin, but a good tip is to go to:

    https://your.server:311

    and login with your admin username and password. That gives you a raw view of the same data that Server Admin.app uses, and you can send commands and examine their output. The output in that case will be XML formatted, which is an optional parameter to serveradmin (the command line equivalent of Server Admin.app).

  • Since I’m not real sure what “Heroes” is I have to say I don’t know why that is funny or not funny. 😉

    Will pullout the PHP books when I get home, unless someone has a quick answer. How would I get the script to write the output to a log file for later review?

    • If you leave this variable as 1,

      $report_disconnection_details = 1;

      then you can call the script like this:

      ./path_to_script.php >> /var/log/afp_disconnection.log

      in say your /etc/crontab, and then that log file would contain the output of the script each time it runs.

  • Nice script, very useful. The first thing I noticed is that some attributes aren’t getting stored as I would expect (i.e. trying to apply the disconnect to specific users, or specific IP). Easy enough fix, but worth mentioning. Simply add the line:

    $value = preg_replace(‘/”/’, ”, $value);

    on line 62, before $connections[$index][$attribute] = …

    that way, you don’t have to test for quotations in the stored array value. ( $connection[‘name’] == “username” ) vs ( $connection[‘name’] == ‘”username”‘ ).

    – b-

  • When running from a crontab, you’ll have to change the line:

    $connected_users_command = “serveradmin command afp:command = getConnectedUsers”;

    to this:

    $connected_users_command = “/usr/sbin/serveradmin command afp:command = getConnectedUsers”;

    it will also have to be run from the system crontab because the serveradmin command must be run as root.

  • Thanks for the script. It worked great on 10.4.9, but seems to be broken in 10.4.11. I’ve run it both though the launchd job I created and manually. They both return this:

    sh: -c: line 1: syntax error near unexpected token `newline’
    sh: -c: line 1: `/usr/sbin/serveradmin command << ‘
    Problem executing /usr/sbin/serveradmin command << , return status was: 2

    Any ideas?

Leave a reply

You must be logged in to post a comment.