Overview #

We did a Migrating From NIS To LDAP project for a client that was using a lot of Solaris with NIS.

We came up with SolarisNISProjectSchema Schema Extensions to make things work in the late 1990s.

As near as we know, projects are a Solaris Specific NIS Map.

The key file to keep track of here is the project database, /etc/project.

The project file contains a series of one-line entries, one for each configured project. (If you don't want to edit the /etc/project file by hand, you can use the projadd, projdel, and projmod commands to add, remove, or modify projects, respectively.)

Each line takes the following form (LDAP Attribute Name):

  • The project-name field (SolarisProjectName) is the name of the project, and must be specified as an alphanumeric string--periods (.) and colons (:) are not allowed.
  • The project-id field (SolarisProjectID) is a unique numerical identifier for the project. The maximum project ID is 2,147,483,647; project IDs between 0 and 99 are reserved for the system.
  • The comment field (description) is a description of the project.
  • The user-list (memberUid) is a list of all the users who are allowed to associate with the project. Wildcards are allowed: an asterisk (*) permits all users to join the project, and an exclamation point (!) followed by a username excludes that user. An exclamation point followed by an asterisk (!*) excludes all users.
  • The group-list field (memberGid) is analogous to the user-list field. Wildcard constructs are valid here, just as they are in the user-list field.
  • The attributes field (SolarisProjectAttr) defines the resource-control attributes associated with the project.

Here are a few of the most "attributes" interesting options:#

task.max-cpu-timeThe maximum amount of CPU time available to all the processes in this project (in milliseconds).
task.max-lwpsThe maximum number of lightweight processes available to all the processes in this project.
process.max-cpu-timeThe maximum amount of CPU time available per process for each process in this project (in milliseconds).
process.max-file-descriptorThe maximum number of file descriptors permitted to each process in this project.
process.max-file-sizeThe maximum file size available to processes in this project (in bytes).
process.max-core-sizeThe maximum size for a core file created by a process in this project (in bytes).
process.max-data-sizeThe maximum heap size for a process in this project (in bytes).
process.max-stack-sizeThe maximum stack size for a process in this project (in bytes).
process.max-address-spaceThe maximum amount of address space (over all segments) available for a process in this project (in bytes).
(There are other resource controls available--these are just the ones that are most immediately interesting.)

Each attribute is specified by setting it equal to a triplet, like this:


There are three available values for privlevel. The first, "basic", means that the threshold can be modified by the process, without any special privileges; the second, "privileged", means that the threshold can be changed only by the superuser; the third, "system", means that the threshold is fixed for the duration of the operating system instance (for example, until a reboot).

Multiple attributes can be specified for a single project; separate them with semicolons.

Now that we've walked through the theory, let's create a project.

We can put the following line in /etc/project:

     test:10000:test project:jqpublic::process.max-file-size=(privileged,16777216,deny)

Alternatively, we could run projadd to create this project:

     # projadd -p 10000 -c 'test project' -U jqpublic test
     # grep ^test: /etc/project
     test:10000:test project:jqpublic::
(Note that projadd and projmod won't let you change the resource-control field.)

This project is named "test" and has a project ID of "10000". Membership is restricted to the user "jqpublic," and any project running in the test project will not be allowed to create a file greater than 16MB (16MB = 16,777,216 bytes).

When jqpublic next logs in, they can run `projects` to get a list of all the projects they are allowed to participate in:

     jqpublic@purgatorio% projects
     default group.staff test
To find out which project is associated with the currently running shell, try id -p:
     jqpublic@purgatorio% id -p
     uid=127(jqpublic) gid=10(staff) projid=10(group.staff)
(A user's default project can be changed by editing /etc/user_attr. The syntax to use for this is "username::::project=projectname". For example:
For more information, consult the man page for user_attr(4).).

In this case, jqpublic's project is 'default.' This project has no resource constraints assigned to it. Let's confirm that the resource limitation works on the maximum file size we defined for the test project:

     jqpublic@purgatorio% id -p
     uid=127(gdm) gid=10(staff) projid=10(group.staff)
     jqpublic@purgatorio% mkfile -v 32M testfile.project=default
     testfile.project=default 33554432 bytes
     jqpublic@purgatorio% newtask -p test csh
     jqpublic@purgatorio% id -p
     uid=127(gdm) gid=10(staff) projid=10000(test)
     jqpublic@purgatorio% mkfile -v 32M testfile.project=test
     testfile.project=test 33554432 bytes
     Could not set length of testfile.project=test: File too large
The resource constraint worked!

You can also set up the resource-management framework so that it writes a notification to the syslog when a resource control is tripped. This can be done via rctladm:

     # rctladm -e syslog process.max-file-descriptor
     # rctladm |grep process.max-file-size
     process.max-file-size       syslog=notice  [ lowerable deny file-size ]
An attempt by a user in the 'test' project to generate a 32MB file generates the following warning in /var/adm/messages:
     Jun 24 23:33:09 british-museum.internal genunix: [ID 883052
kern.notice] privileged rctl process.max-file-size (value 16777216)
exceeded by process 2428

One other interesting feature about projects is that the prstat command can summarize running processes by project, if you give it the -J switch. This can be quite useful if, for example, you have a "Webserver" project to which all your Web server daemons belong. (If you aren't familiar with prstat, I encourage you to play around with it: it's a useful application. It gives output that is quite similar to that of top, but it is more lightweight. It became available in Solaris 8.)

jqpublic@purgatorio% prstat -cJ 

More Information#

There might be more information for this subject on one of the following: