Operating Systems



Apply operating system tools

Contents:

Operating systems 2

Using operating system services 2

Scripting for system administration 4

Example scripts 5

WMI scripting 6

Logging 8

Advanced topics 10

Summary 10

Operating systems

In the early days of computing, each program the computer ran was a 'job' for a human computer operator. The operator would set up all the computer's registers, load the job into the computer's memory (using punch cards or paper tape), and set the program running. Only one program would run at a time, and that program had exclusive use of the computer system's resources including the memory, the printer, the terminal, and so on.

Nowadays, every aspect of the computer's operation is handled by the 'operating system' such as Microsoft Windows, Apple OS or Linux. Operating systems are sophisticated software systems that:

• Enable multiple applications to run at the same time (or at least, appear to run at the same time).

• Manage the shared access to resources such as memory, disks, the file system, printers, scanners, mouse, sound cards, video cards, network cards and so on.

• Allow multiple users to coexist on the same system, while protecting the security of each user's work.

• Enable multiple computers to be networked together and cooperate.

Using operating system services

To do anything useful, your program will ultimately be using the services of the operating system. Whenever your program needs to do any of the following, it will be using the operating system:

• Print something to the screen.

• Read something from the keyboard.

• Open a file.

• Go to a particular directory (folder).

• Communicate on a network.

• Find out the time.

• Launch another application.

• Respond to system events.

In fact, even the memory that your variables and objects live in must be ultimately requested from the operating system.

The good news is that in most cases the Python interpreter takes care of all the details for you. So when you use the print, or raw_input functions, you don’t need to do anything special - you simply use the function.

Generic system services

Wherever possible, you should use the standard Python functions or modules. The advantage of including Operating System services in the standard library is that you code will look the same on different operating systems. So when you open a file, you only need to go:

myFile = file('myfile.txt', 'r')

whether you are running on Windows, Linux, or a Mac. Therefore, you can use the same program on multiple platforms without writing system-specific code for each one. This makes programs much easier to write and maintain.

Another advantage is that the programming is simpler if you use Python library modules. The library will handle all of the messy details of dealing with particular operating systems, including COM on Windows, or OS traps on UNIX-like systems.

Some services such as basic file operations and console input and output are built into the Python core. Others are available in library modules. If you look at the Python documentation under 'Library Reference/Generic Operating System Services', you will see the services that you can use.

Wherever possible, you should use these generic, platform-independent interfaces in preference to writing code for only one platform. If you don’t find a module in the standard distribution, you should spend some time looking for one on the internet, and in the Python 'cheese shop' at . For example, there is no generic module for playing sound files included with the standard Python distribution. But there is a cross-platform module called PyMedia available, which you could download an install.

Platform-specific services

Unfortunately, there will not always be a generic Python interface for every possible operation you might want to perform. In this case, you will need to write code that is usable on only one platform (such as Microsoft Windows).

You are forced to do this in three situations.

• A generic library may not have been written yet for this type of operation.

• Only one operating system supports the operation, so a generic interface is not possible.

• You need greater control than the generic interface provides.

Operating systems differ in the detailed features they provide, but a generic interface will only be able to give you the features common to both systems. The particular API of an operating system will allow more fine-grained control, or perhaps greater speed.

An example of this is file handling. Python provides good access to files in a standard way, and these facilities are fine for almost all cases. Occasionally however, applications may need to access specific features for files such as encryption, or file linking and shortcuts, or accessing special system-specific document properties.

You should think carefully before you use platform-specific features because your program will only work on one computer platform, and will be harder to write.

Scripting for system administration

In systems administration scripting, we cannot usually avoid using system-specific services. This is because by definition, we are querying or controlling aspects of the operating system itself. Often, we will want to poke about in places that a 'normal' program would never want (or be allowed) to go. Some of the things you might want to do include:

• Query the system event logs.

• Install new software.

• Manage user accounts and groups.

• Manage security.

• Start a new task at a particular time.

• Log-on to a computer as a particular user.

• Check what software, or what version of software is installed.

• Check the available disk space on all computers.

• Check is all security updates are installed.

Each of the above operations may involve multiple computers. For example, you may want to produce reports listing all the software on every workstation, or to check whether all workstations on a network have the latest operating system critical updates installed.

Windows services

Thanks to the win32 extensions modules by Mark Hammond, Python has a good interface to the Microsoft Windows Application Programming Interfaces (APIs).

You can access a function through a low-level API, or via one or more increasingly higher-level APIs. For example, some networking functions can be accessed using the low-level Windows APIs, by the Network Management APIs, by the Active Directory APIs, or by the Windows Management Instrumentation APIs. These four represent increasing level of generality and sophistication. Generally speaking, it's best to use the highest logical level that will allow you to do the job. This is especially true in scripting, where we need to worry less about performance and compatibility issues for example.

Note: We are using the term 'service' in the very general sense of the operating system providing a service, in other words doing something for us when requested. In Microsoft Windows, the term 'Service' is used to refer to a background process, which is a completely different concept.

Example scripts

Below we give a range of examples of Python scripts for Windows scripts which use operating system services.

Beep!

Here is a simple script to get us started. The standard Python distribution contains a library module called winsound that can be used to play sounds on Windows operating systems. One of the functions in this module allows us to play a sound with a particular frequency for a particular time. The program below plays a 400 Hz tone for 2000 milliseconds (i.e. 2 seconds).

import winsound

winsound.Beep(400, 2000)

You can also play the standard Windows system sounds as defined in the Windows Control Panel under 'Sounds and Audio Devices'. For example, this program plays the 'system exclamation' sound:

import winsound

winsound.PlaySound('SystemExclamation', winsound.SND_ALIAS)

Starting a process.

You may want to start another application from your script. This is easy to do in Python using one of the spawn commands. The example below will start the notepad program as a new process.

import os

os.spawnl(os.P_NOWAIT, r'C:\windows\notepad.exe', '')

You can vary the behaviour of this example in many ways, including passing arguments to the started program (in this case it could be a file name for notepad to open), setting environment variables, or waiting for the started process to finish. The 'r' before the notepad command string means 'raw', which is required so that the backslash characters do not have special meaning.

If you want to get the output of a simple Windows shell command, you can start a command and open a 'pipe' to your own program, to gather the output. In the example below, we gather the output of the 'dir' (directory listing) command. (Note that there are better ways to get a directory listing using Python, without having to start another process!).

import os

pipe = os.popen('dir', 'r')

output = pipe.read()

print output

WMI scripting

Windows Management Instrumentation (WMI) is a set of objects that allows the programmer to access or control almost any imaginable aspect of a networked computer system (provided of course, they have sufficient level of privilege).

Most of the remaining examples in this reading use WMI. You can modify these scripts to suit your needs.

Scheduling a task

If you need to start a task once at some specified time, or repeatedly (every day or every week for example), you use the scheduler. This is typically done with programs such as virus scanning software, which needs to run regularly to maintain a virus-free system. You may want some of your scripts to run regularly, for example to generate reports used for system management and statistics.

In Windows, you can schedule tasks manually by opening 'Scheduled Tasks' from the Windows Control Panel. Then you add a new item by selecting File/New/Scheduled Task, and fill in the details.

This can also be done from a script as shown below.

import win32com.client

objWMIService = win32com.client.Dispatch('WbemScripting.SWbemLocator')

objSWbemServices = objWMIService.ConnectServer('.', 'root\cimv2')

jobService = objSWbemServices.Get('Win32_ScheduledJob')

inParam = jobService.Methods_("Create").InParameters.SpawnInstance_()

inParam.Properties_.item('Command').Value = 'Notepad.exe'

inParam.Properties_.item('StartTime').Value =\

'********180000.000000+600'

inParam.Properties_.item('RunRepeatedly').Value = True

inParam.Properties_.item('DaysOfWeek').Value = 1

jobService.ExecMethod_('Create', inParam)

The code above is complicated because Component Object Model (COM) interfaces are being used. The objects and functions cannot be called directly as with a native Python object or function.

The first three lines are about getting access to the 'Win32_ScheduledJob' interface. Firstly, we ask COM to give us a handle to the WMI service. Then we connect to that service, requesting access to the current computer only by using the string '.' Next, we ask WMI for a handle to the object we wish to use - the 'Win32_ScheduledJob' service.

The last six lines are logically equivalent to just one function call to the 'Create' method of the 'Win32_ScheduledJob' object. First we get an object for the parameters, then we add the parameters one by one, including the application name ('notepad.exe'), the time for the application to run (6 PM or 18:00), and the days of the week we want to run (in this case, on Mondays). Then we call the create function using the 'ExecMethod'

If you run this script, then look at the scheduled tasks list, you will see that a new task has been added as shown below.

[pic]

Displaying scheduled tasks

We can also get a list of all the scheduled tasks on the current computer using script using the code shown below.

import win32com.client

objWMIService = \

win32com.client.Dispatch('WbemScripting.SWbemLocator')

objSWbemServices = objWMIService.ConnectServer('.', 'root\cimv2')

jobs = objSWbemServices.ExecQuery('SELECT * FROM \

Win32_ScheduledJob')

for i in jobs:

print 'Application = ', mand

print 'Start Time =', i.StartTime

if i.DaysOfWeek:

print 'Days of Week:', i.DaysOfWeek

if i.DaysOfMonth:

print 'Days of Month:', i.DaysOfMonth

The first two lines of code again connect to the WMI service. Then we execute a query in a language similar to SQL called WQL (the WMI Query Language). The query string

'SELECT * FROM Win32_ScheduledJob'

merely requests every Scheduled Job. This returns a list of jobs on the current machine, which we place in the variable 'jobs'.

The remainder of the program is simply cycling through this list using a for statement, printing the details of each scheduled job. If you run this program after adding a job as described in the previous section, you will see the details of that job.

Free space on hard drives

In the example below, we query the local hard disks (DriveType = 3). For most workstations, this will result in only one logical drive, the C: drive. We print the percentage free space by using the FreeSpace and Size attributes of each drive. Similar programs can be written to get information on most system components.

import win32com.client

objWMIService = win32com.client.Dispatch('WbemScripting.SWbemLocator')

objSWbemServices = objWMIService.ConnectServer('.', 'root\cimv2')

disks = objSWbemServices.ExecQuery('SELECT * FROM \

Win32_LogicalDisk WHERE DriveType=3')

for d in disks:

percentFree = float(d.FreeSpace) / float(d.Size) * 100

print 'Free space on drive',

print d.caption, ' = ',

print '%2.2f %%' % percentFree

Logging

Applications sometimes need to add events to a system log to document the fact that important things have happened. These events may be

• a normal occurrence such as a Windows subsystem starting up, or a user logging on to the system.

• a warning (such as the system running low on memory, or other resources

• an error such as an application being shut down for attempting an illegal operation, or being killed by the user.

Logging events

Logging is such a common requirement that it is included with standard Python. The logging functionality is implemented in the logging module. The example below logs two events, one has severity of 'error' and one of severity 'information'.

import logging

import logging.handlers

# Get a Python logger object for our application

logger = logging.getLogger('myapp')

# We want a log handler that will add events to

# the NT system logs

hdlr = logging.handlers.NTEventLogHandler('My Application')

# register this handler with the logger

logger.addHandler(hdlr)

# set the minimum error level that will be logged

# we want to log everything, so we set the level

# to the minimum of INFO

logger.setLevel()

logger.error('We have a problem')

('Its five oclock now!')

logging.shutdown()

Notes:

• The PythonWin IDE seems not to destroy the logger object between runs. If you find more events in the log that you expected, use the command line to run this script instead.

• WMI also allows the logging of events, but we have used the standard Python library, in keeping with the principle of using the most generic method available.

Reading the event log

WMI allows us to easily read the Windows event logs from script. The example below reads the messages we wrote in the previous example.

import win32com.client

objWMIService = \

win32com.client.Dispatch('WbemScripting.SWbemLocator')

objSWbemServices = objWMIService.ConnectServer('.', 'root\cimv2')

colItems = objSWbemServices.ExecQuery('SELECT * FROM \

Win32_NTLogEvent WHERE SourceName = "My Application"')

print 'Logged data from My Application'

print '==============================='

for item in colItems:

print "%-20s %-12s %-22s %-30s" % (item.SourceName,\

item.Type, item.TimeGenerated, item.Message)

Notes:

• the backslashes ('\') at the end of lines are the way to continue long lines in Python.

• the print statement contains a formatting expression. See the Python Library Reference section 2.3.6.2 'String Formatting Operations' for details.

• Note the query string contains a WHERE clause, which restricts the set of events returned to those from our application in the previous example.

Advanced topics

The above only scratches the surface of the depth and breadth of facilities provided by the operating system. Here we will just mention a few more things to whet your appetite for further study.

Windows automation

Windows allows you to do much more than simply start another process. Using the 'Automation' features exposed by some applications, you can start an application, and then do almost anything from a script that you could do by using the application directly. The Microsoft Office applications can all be automated in this way. The topic of automation scripting is beyond the scope of this reading. For more information, see the Microsoft Windows Scripting Guide.

Summary

• Operating Systems provide a great many services for applications that run under them.

• Scripts can control other tasks, including running system commands, running other applications, and scheduling a program to run at a particular time.

• In Microsoft Windows systems, you can easily query or control many aspects of hardware and software using WMI.

• Logging events is a common requirement, and we can interface to the MS-Windows event logs from Python.

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download