Mac Commands - Directory Editor, dscl and Custom Inventory


Article ID: 181718


Updated On:


Inventory Solution for Mac




This article provides an overview of the Mac OS X Directory Editor and associated dscl command line utility. It includes examples of using the Symantec Management Platform’s Custom Inventory for Mac to gather this directory data. This article is intended to present this information simply yet detailed enough to get started. 
The directories available to a Mac include the local directory on the Mac, Active Directory on domain, etc. 
WARNING: Keep in mind that accessing production data without authorization may be a violation of company policy and/or government laws. You are advised to check with your company prior to accessing production company data to avoid any issues arising due to unauthorized access. All testing for this document was done on a test Mac computer and a test Active Directory server with dummy data. 
Overview of the Directory Editor and dscl command
The Mac OS X ‘Directory Utility’ provides functionality to bind a mac computer to a domain, enable/disable the root user and several other features. This utility is found in /System/Library/CoreServices/Directory 
One of the lesser-known features of the Directory Utility is the “Directory Editor”. 
The command line version of this feature is ‘dscl’, which is described in its man page as the “Directory Service Command Line Utility”. 
Both the Directory Editor and the dscl command allow for connecting to, querying and interacting with a directory. 
Note: ‘~=’ means ‘equals or roughly equal to’ in this document. 
Node ~= datasource ~= (server and database). The node can specify a local database or a database hosted on another machine. Sample nodes are similar to the following: 
/Active Directory/MYDOM0/All Domains
The first row shows a node to the Default database on the Local mac computer. The second row is for the All Domains Active Directory database in the specified domain. 
The dscl utility has several operations that can be performed on a database record. Among them are list, read, readall, create, delete, merge, change, etc. See ‘man dscl’ for more details on available commands. This document will only deal with the read type of commands. 
Path ~= (table and record). The path typically includes the database table name and the record name. Examples include: 
Users johndoe
Computers mymac$
The Directory Editor
In the Directory Editor screen, servers and databases are shown in the ‘nodes’ drop-down list:
Tables, or the first portion of the ‘path’ for the selected node, are shown in the ‘Viewing’ drop-down list:
Individual records, or the second portion of the path, are then shown in the left-pane of the app’s screen. In this case, the only local computer is the ‘localhost’, which makes sense. Once a record is selected from the list in the left-pane, individual attributes and corresponding data for that record are shown in the main portion of the window, as shown here:
This is the basic process for finding database data using the Mac Database Editor and dscl command line: Select or specify a server and database (node or datasource), then select a table and record (path). It is then possible to see individual attributes such as ipaddress, DNSName, etc. 
The ‘dscl’ Command
The dscl command is run from a shell prompt using the Terminal app or an equivalent app. It has two modes – interactive and non-interactive. The dscl command returns the same data shown in the Directory Editor app. 
Note: Most names are case-sensitive when using the dscl command. 
Interactive Mode
Typing ‘dscl’ at a shell prompt and pressing ‘enter’ provides access to the interactive mode. Interactive mode displays a ‘>’ prompt. At that point, dscl is waiting for further commands. To quit interactive mode, type the letter ‘q’ and press ‘enter.’ 
Note that the ‘ls’ and ‘cd’ commands work within interactive mode. This allows for viewing entries at the current location and to traverse the node and path. The prompt will include the current location in the directory path. 
Non-Interactive Mode
In non-interactive mode, the entire command is entered on one line, the resulting output is displayed on-screen, followed by the normal shell prompt. 
The general syntax of this command is to specify a node, a command to perform, a path and, optionally, a list of attributes or columns.
Node, command, path, attributes
data source and database, command, table and record, attributes
Note that attributes are optional. Not specifying attributes returns all attributes in the specified table. Viewing all attributes of a table may be helpful for determining attribute names and which attributes are most helpful for a given requirement. 
Sample non-interactive commands: 
dscl /Local/Default read Computers/localhost IPAddress
dscl  /Active\ Directory/MyDomSrv/ -read /Computers/mymacpro$ distinguishedName 
Note that the node, command and path must be specified in this order. It does not seem possible to specify the command, node/path or other variations. 
Sample Interactive sequence to read localhost data
$ dscl
Entering interactive mode... (type "help" for commands)
> ls
> cd /Local/Default
/Local/Default > read Computers/localhost
dsAttrTypeNative:KerberosFlags: 110
AppleMetaNodeLocation: /Local/Default
IPv6Address: ::1 fe80::1%lo0
KerberosServices: host afpserver cifs vnc
RecordName: localhost
RecordType: dsRecTypeStandard:Computers
/Local/Default > 
Sample Non-interactive command to read localhost data
$ dscl /Local/Default read Computers/localhost
dsAttrTypeNative:KerberosFlags: 110
AppleMetaNodeLocation: /Local/Default
IPv6Address: ::1 fe80::1%lo0
KerberosServices: host afpserver cifs vnc
RecordName: localhost
RecordType: dsRecTypeStandard:Computers
Sample Non-interactive command to read a single attribute from the localhost record
$ dscl /Local/Default read Computers/localhost IPAddress
The following examples show the interactive and non-interactive commands for gathering the DNSName, RealName, and RecordName from Active Directory for a specific computer.  
Sample Interactive command to read specific active directory computer data
$ dscl
Entering interactive mode... (type "help" for commands)
> cd Active\ Directory/MYDOM0/All\ Domains/Computers
/Active Directory/MYDOM0/All Domains/Computers 
> ls
/Active Directory/MYDOM0/All Domains/Computers > read MYNB$ DNSName RealName RecordName
RealName: MYNB
RecordName: MYNB$
Note in the interactive sample, above, the database name (Computers) was included in the node portion of the command. The non-interactive mode does not allow for putting the database in the node. The following two non-interactive commands show the incorrect and correct node and path syntax, respectively. (There may be variations to this rule.)
Sample Non-interactive command to read active directory computer data
* The node is enclosed in double quotes since it contains spaces. 
$ dscl "/Active Directory/MYDOM0/All Domains/Computers" -read MYNB$ DNSName RealName RecordName
Data source (/Active Directory/MYDOM0/All Domains/Computers) is not valid.
$ dscl "/Active Directory/MYDOM0/All Domains" -read Computers/MYNB$ DNSName RealName RecordName
RealName: MYNB
RecordName: MYNB$
Custom Inventory to Gather Database Information
At this point, we are ready to create a custom inventory script to gather specific data. Following are two custom inventory samples that use ‘dscl’ to gather directory data. 
Note: The first line of each script is commented so the helper script is not included. This allows for seeing the output on-screen without sending the results to the NS/SMP server. To actually send the data to the NS/SMP server, remove the beginning ‘#’ sign. 
Note: Those with greater programming skills may be able to reduce the number of ‘dscl’ commands executed in these scripts. Feel free to share the code, if you do. ☺
Gathering Local User information
#. `aex-helper info path -s INVENTORY`/lib/helpers/
# specify custom inventory data class, attributes, etc. 
echo cust_mac_localusers
echo "Delimiters=\" \""
echo "string250 string50 string250 string250 string50 string250"
echo "NFSHomeDir PrimaryGroup RealName RecordName  UniqueID UserShell"
# list users, get data for each user
for i in `dscl  /Local/Default -list /Users`; do 
  uniqueID=`dscl  /Local/Default -read /Users/$i UniqueID | awk '{ print $2 }'`
  # exclude system-created users, which have IDs below 500
  if [ "${uniqueID:-0}" -ge 500 ]; then
    nfsHD=`dscl  /Local/Default -read /Users/$i NFSHomeDirectory | awk '{ print $2 }'`
    pGroupID=`dscl  /Local/Default -read /Users/$i PrimaryGroupID | awk '{ print $2 }'`
    realName=`dscl  /Local/Default -read /Users/$i RealName | awk '{ print $2 }'`
    recName=`dscl  /Local/Default -read /Users/$i RecordName | awk '{ print $2 }'`
    userShell=`dscl  /Local/Default -read /Users/$i UserShell | awk '{ print $2 }'`
    echo $nfsHD $pGroupID $realName $recName $uniqueID $userShell
Gathering Active Directory Computer Names
#. `aex-helper info path -s INVENTORY`/lib/helpers/
# specify custom inventory data class, attributes, etc. 
echo cust_ad_computernames
echo "Delimiters=\" \""
echo string50 string50 string50
echo "RealName DNSName DistinguishedName"
# get a list of computers in AD and return specific attributes; use awk to exclude the attribute name and return only the value. 
for i in `dscl  /Active\ Directory/MYDOM0/ -list /Computers`; do 
  realName=`dscl  /Active\ Directory/MYDOM0/ -read /Computers/$i RealName | awk '{ print $2 }'`
  dnsName=`dscl  /Active\ Directory/MYDOM0/ -read /Computers/$i DNSName | awk '{ print $2 }'`
  distName=`dscl  /Active\ Directory/MYDOM0/ -read /Computers/$i distinguishedName | awk '{ print $2 }'`
  echo $realName $dnsName $distName
The above two samples are attached below. 


Attachments get_app get_app