Handling Resource-intensive Operations with a Queue

Một phần của tài liệu Pro PHP Security phần 9 pps (Trang 38 - 53)

Managing a queue of possibly delayed resource-intensive jobs is much more complex than handling root-level operations, and therefore exposes your server and your users’ data to avoidable risks. We turn to that task now, concentrating on three different problems:

1. How to build a queue of jobs so that they are not executed in an unsafe manner 2. How to trigger batch-processing scripts so that they can be executed safely by the batch

processor

3. How a web application can track the status of a background job and pick up the results when complete

How to Build a Queue

Creating a queue so that your web application can start handing off jobs is the first step in managing these resource-intensive jobs in a safe manner, so that executing them doesn’t endanger either your server or your users’ data.

434 C H A P T E R 2 2 ■ S A F E L Y E X E C U T I N G S Y S T E M C O M M A N D S

Using a Drop Folder for Short-term Queuing

The simplest kind of queue, suitable for use with tasks that can be completed without too much delay, is a folder in which the web application writes data to be processed. The batch processor checks the folder for new files, which it recognizes either by time (it was created in the interval since the processor checked last) or by naming convention (it has, for example, a _Vh extension). The processor then sends the data off to be processed by the system, instructing it to put the results where the web application (which has been waiting patiently) can find them and send them back to the user.

When working with files in a drop folder, the batch processor must be able to answer each of these four questions:

1. Which files still need to be processed?

2. Are there any files that look like they are being processed, but in fact are not, due to error or system restart during processing?

3. Where should the results be saved?

4. What happens to the original files after processing?

Strategies for answering these questions include moving files-in-progress to a different folder, renaming files to keep track of state and which process ID is actively working with the data, and using a second drop folder to store the results where they can be found by the web application. The daemon may clean up leftover original and processed files on its own, or rely on a separate garbage-collection script.

Using IMAP for Longer-term Queuing

There are a number of queues that already exist on any system, email being one of the most common and robust. In fact, the system mail-handling facility provides a built-in solution to the problem of queuing batch jobs that are going to require substantial amounts of processing time. By formatting job requests as email messages, you can take advantage of the existing email infrastructure, and use an IMAP mailbox as a processing queue.

Under this scheme, when your batch-processing script is awakened, it checks the applica- tion’s inbox for new messages. It then examines those messages for valid requests, spawning a child process to handle each one, up to a predetermined limit. It deletes and expunges any bogus messages from the inbox.

When each child process is finished, it cleans up by moving its message out of the inbox and into another folder, appending the results as an attachment. The web application can pick the results up from there, and either delete the message, or better yet, mark it as read and leave it in the folder as a record of the job. IMAP servers can efficiently handle mail folders with thou- sands of messages in them.

On a server with IMAP already installed, or easily installable via package or port, using email as a messaging and job queueing system like this could save you a lot of time imple- menting your own. While this will add to the complexity of your application by expanding the

SnyderSouthwell_5084C22.fm Page 434 Thursday, July 28, 2005 3:00 PM

number of subsystems you need to talk to, mail and IMAP servers are robust and proven secure by widespread daily use on the Internet. On the other hand, if you develop or deploy your application on a server that doesn’t have IMAP support, or you need to port the application to a nonserver operating system down the line, you might want to skip this option and build your own queue.

Using a Database for Queuing

An alternative to the IMAP method for handling resource- and therefore time-intensive batch jobs is to store them in a database. This has the advantage of being possible even when an IMAP server is not available. It also relies on a familiar, rather than a slightly unusual, manage- ment interface.

The MySQL code for creating such a database table might look something like this:

4C62E6E23=6[`Sd

ZU:?EF?D:8?652FE@P:?4C6>6?EAC:>2CJ<6J cVbfVdeE6IE

TcVReVU52E6E:>6 deRceVU52E6E:>6 WZ_ZdYVU52E6E:>6 UReRE6IE

cVdf]eE6IE

deRefdG2C492C#&&

:?56IZiPdeRefddeRefd ,

Your processor script would need to retrieve unprocessed jobs based on their status, send them off for processing (and update the deRceVU and deRefd fields), store the results (and again update the WZ_ZdYVU and deRefd fields), and notify the user that the results are available for retrieval. Here is a PHP class to handle these tasks. It can be found also as [`S>R_RXVc4]RddaYa in the Chapter 22 folder of the downloadable archive of code for Pro PHP Security at

Yeea+ hhhRacVddT`^. -0aYa

T]Rdd[`S>R_RXVcl

afS]ZTZU, eYVcVT`cUZUZ_eYV[`SdUS afS]ZTcVbfVde, cVbfVdee`ac`TVdd`cRaZ

afS]ZTTcVReVU, ^jdb]UReVeZ^V`WZ_dVceZ`_Z_eYVbfVfV afS]ZTdeRceVU, ^jdb]UReVeZ^V`WdeRce`Wac`TVddZ_X afS]ZTWZ_ZdYVU, ^jdb]UReVeZ^V`WV_U`Wac`TVddZ_X

afS]ZTUReR, `aeZ`_R]UReRe`SVfdVUZ_TRccjZ_X`fecVbfVde afS]ZTcVdf]e, cVda`_dVe`cVbfVde

afS]ZTdeRefd, deRefd`WeYV[`S+_Vhcf__Z_X`cU`_V acZgReVUS, UReRSRdVYR_U]VR_`aV_^jdb] ^jdb]ZUReRSRdV

436 C H A P T E R 2 2 ■ S A F E L Y E X E C U T I N G S Y S T E M C O M M A N D S

T`_decfTe`cRddZX_dUSYR_U]V afS]ZTWf_TeZ`_PPT`_decfTeUSl ZWXVePT]RddUS.^jdb]Zl

eYc`h_Vh6iTVaeZ`_MUSaRddVUe`T`_decfTe`c Zd_`eR^jdb]Z`S[VTe, n

eYZd/US.US, n

Z_dVceZ_dVcedeYV[`SZ_e`eYVbfVfV afS]ZTWf_TeZ`_Z_dVcel

ZWV^aejeYZd/cVbfVdel

eYc`h_Vh6iTVaeZ`_HZ]]_`eZ_dVce[`ShZeYV^aejcVbfVde, n

bfVcj.:?D6CE:?E@[`SdD6EZU.

cVbfVde.leYZd/VdTeYZd/cVbfVden TcVReVU._`h

UReR.leYZd/VdTeYZd/UReRn deRefd._Vh,

cVdf]e.eYZd/US/bfVcjbfVcj, ZWcVdf]el

eYc`h_Vh6iTVaeZ`_F_RS]Ve`Z_dVce[`SfdZ_XbfVcjbfVcj eYZd/US/Vcc`c,

n

XVeZU`WZ_dVceVUcVT`cU eYZd/ZU.eYZd/US/Z_dVcePZU,

]`RU[`SSRT\Wc`^UReRSRdVe`XVeTcVReVUUReV eYZd/]`RU,

cVefc_ECF6, n

[`S>R_RXVc4]RddaYaT`_eZ_fVd

You initialize the class by setting a large group of public variables, all with self-explanatory names, and one private variable, a database resource. The constructor method simply checks whether that resource is valid. There follows then the first of a whole set of methods, in this case Z_dVce, all of which have very similar structures:

• Checks for various error conditions

• Constructs a query

• Checks that the query executed successfully

• Stores the results in appropriate class variables

• Returns with an appropriate value

SnyderSouthwell_5084C22.fm Page 436 Thursday, July 28, 2005 3:00 PM

T`_eZ_fVd[`S>R_RXVc4]RddaYa

]`RU^VeY`U]`RUdeYV[`ShZeYeYZd/ZUWc`^eYVUReRSRdV afS]ZTWf_TeZ`_]`RUl

ZU^fdeSV_f^VcZT

ZWZdP_f^VcZTeYZd/ZUl

eYc`h_Vh6iTVaeZ`_;`S:5^fdeSVR_f^SVc, n

SfZ]UR_UaVcW`c^D6=64EbfVcj

bfVcj.D6=64E7C@>[`SdH96C6ZU.eYZd/ZU, cVdf]e.eYZd/US/bfVcjbfVcj,

ZWcVdf]eeYc`h_Vh6iTVaeZ`_;`SeYZd/ZUU`Vd_`eViZde, T`_gVcec`hRccRjZ_e`[`S`S[VTe

c`h.cVdf]e/WVeTYPRdd`T, W`cVRTYc`h2D\Vj./gR]fVl eYZd/l\Vjn.gR]fV,

n

cVefc_ECF6, n

_Vie^VeY`UWZ_UdR_U]`RUdeYV_Vief_deRceVU[`S afS]ZTWf_TeZ`__Viel

SfZ]UR_UaVcW`c^D6=64EbfVcj

bfVcj.D6=64E7C@>[`SdH96C6deRefd._Vh

@C56C3JTcVReVU2D4=:>:E", cVdf]e.eYZd/US/bfVcjbfVcj, ZWcVdf]el

eYc`h_Vh6iTVaeZ`_6cc`c`_bfVcjbfVcj eYZd/US/Vcc`c, n

WVeTYc`hcVefc_72=D6ZW_`c`hdW`f_U c`h.cVdf]e/WVeTYPRdd`T,

ZWV^aejc`hcVefc_72=D6, ]`RUc`hZ_e`[`S`S[VTe W`cVRTYc`h2D\Vj./gR]fVl eYZd/l\Vjn.gR]fV,

n

438 C H A P T E R 2 2 ■ S A F E L Y E X E C U T I N G S Y S T E M C O M M A N D S

cVefc_eYZd/ZU, n

deRce^VeY`U^Rc\dR[`SRdSVZ_XZ_ac`XcVdd afS]ZTWf_TeZ`_deRcel

ZU^fdeSV_f^VcZT

ZWZdP_f^VcZTeYZd/ZUl

eYc`h_Vh6iTVaeZ`_;`S:5^fdeSVR_f^SVc, n

SfZ]UR_UaVcW`c^FA52E6bfVcj

bfVcj.FA52E6[`SdD6EdeRceVU._`hdeRefd.cf__Z_X H96C6ZU.eYZd/ZU,

cVdf]e.eYZd/US/bfVcjbfVcj, ZWcVdf]el

eYc`h_Vh6iTVaeZ`_F_RS]Ve`faUReV[`SfdZ_XbfVcjbfVcj eYZd/US/Vcc`c,

n

]`RUcVT`cUSRT\Wc`^USe`XVefaUReVUWZV]Ud eYZd/]`RU,

cVefc_ECF6, n

WZ_ZdY^VeY`U^Rc\dR[`SRdT`^a]VeVU afS]ZTWf_TeZ`_WZ_ZdYdeRefd.U`_Vl ZU^fdeSV_f^VcZT

ZWZdP_f^VcZTeYZd/ZU

eYc`h_Vh6iTVaeZ`_;`S:5^fdeSVR_f^SVc, SfZ]UR_UaVcW`c^FA52E6bfVcj

bfVcj.FA52E6[`Sd

D6EWZ_ZdYVU._`h

cVdf]e.leYZd/VdTeYZd/cVdf]en deRefd.leYZd/VdTdeRefdn H96C6ZU.eYZd/ZU,

cVdf]e.eYZd/US/bfVcjbfVcj, ZWcVdf]el

eYc`h_Vh6iTVaeZ`_F_RS]Ve`faUReV[`SfdZ_XbfVcjbfVcj eYZd/US/Vcc`c,

SnyderSouthwell_5084C22.fm Page 438 Thursday, July 28, 2005 3:00 PM

]`RUcVT`cUSRT\Wc`^USe`XVefaUReVUWZV]Ud eYZd/]`RU,

cVefc_ECF6, n

VdTfeZ]ZejVdTRaVdRdecZ_XW`cfdVZ_RUReRSRdVbfVcj afS]ZTWf_TeZ`_VdTdecZ_Xl

cVefc_eYZd/US/cVR]PVdTRaVPdecZ_XdecZ_X, n

V_U`W[`S>R_RXVcT]Rdd n

0/

The remaining methods, all named revealingly, follow the same general outline as the one discussed earlier. We will demonstrate the use of this class later in the chapter.

Triggering Batch Processing

Now that we’ve examined different methods for creating a queue, we turn to triggering the actual batch processing, which again must be done in a manner that minimizes any risk to your server or your users’ data. We will demonstrate two possibilities: using the Tc`_ daemon to periodically start batch processing, and building your own daemon in PHP to watch for and execute queued jobs.

Using FURQ to Run a Script

The system daemon Tc`_ runs as the c``e user but can switch to the identity of any user when executing scheduled tasks. It wakes up periodically and checks a series of configuration files (called Tc`_eRSd; each user has one) to see if there are any scheduled jobs that should be executed. If so, the commands are executed as the Tc`_eRS owner, and the output is emailed to any recipients configured in the Tc`_eRS. Then Tc`_ sleeps until the next wakeup period.

You could choose to have Tc`_ run your batch-processing script periodically, say, every three minutes. If you do this, however, you will need to create some mechanism that keeps two or more scripts from trying to process the same queue entry. This is because, if one batch processor takes longer than the scheduled three minutes to work through the jobs in the queue, it will still be running when Tc`_ triggers the next batch processor. To keep things simple in the preceding example, we first check to see whether an earlier batch-processing script is still active, exiting if that is the case. A more complex implementation might look at other factors, such as the system CPU load average, to see if there is room to run additional batch-processing instances.

The following script is meant to be called periodically by Tc`_. It uses lockfiles to discover concurrent processes so that it doesn’t start too many parallel MP3 encoders. This code can be found also as ^a$Ac`TVdd`caYa in the Chapter 22 folder of the downloadable archive of code for Pro PHP Security at Yeea+ hhhRacVddT`^.

440 C H A P T E R 2 2 ■ S A F E L Y E X E C U T I N G S Y S T E M C O M M A N D S

-0aYa ]`XWZ]V

]`X.^a$Ac`TVdd`c]`X,

]Z^Ze`__f^SVc`WT`_TfccV_eac`TVddVd T`_TfccV_Tj=Z^Ze.#,

Uc`a7`]UVc

Uc`a7`]UVc. e^a ^a$Uc`a, RfUZ`V_T`UZ_XT`^^R_U

]R^V. `ae ]`TR] SZ_ ]R^VbfZVe, XVeac`TVdd:5

aZU.a`dZiPXVeaZU,

TYVT\W`chRgWZ]VdR_U[`SWZ]Vd UZc.UZcUc`a7`]UVc,

hRgd.RccRj, [`Sd.RccRj,

TYVT\Uc`aW`]UVcW`c]`T\WZ]VdhZeY[`SVieV_dZ`_R_UhRgWZ]Vd hYZ]VV_ecj.UZc/cVRUl

aReY.Uc`a7`]UVc V_ecj, ZWZdPUZcaReYT`_eZ_fV, aReYZ_W`.aReYZ_W`aReY,

ZWaReYZ_W`LVieV_dZ`_N...[`Sl WZ]V_R^V.aReYZ_W`LSRdV_R^VN,

[`SdLWZ]V_R^VN.Uc`a7`]UVc WZ]V_R^V, T`_eZ_fV,

n

ZWaReYZ_W`LVieV_dZ`_N...hRgl hRgdLN.aReY,

n n

UZc/T]`dV, f_dVeUZc,

^a$Ac`TVdd`caYaT`_eZ_fVd

SnyderSouthwell_5084C22.fm Page 440 Thursday, July 28, 2005 3:00 PM

The script initializes by setting necessary variables, and extracts a list of the existing hRg and [`S files from the drop folder.

T`_eZ_fVd^a$Ac`TVdd`caYa ZWV^aejhRgdl

ac`TVdd`c=`X?`hRgdW`f_U, n

V]dVl

W`cVRTYhRgW`f_UTYVT\e`dVVZWZedSVZ_XYR_U]VU `cZWeYVcVRcVe``^R_j[`SdR]cVRUjRTeZgV

W`cVRTYhRgd2DaReYl

ZWZ_PRccRjaReY[`SdT`f_e[`Sd-T`_TfccV_Tj=Z^Zel cVRUje`V_T`UV

ac`TVdd`c=`X4`_gVceZ_XaReYe`^a$, TcVReVR]`T\WZ]V

aReYZ_W`.aReYZ_W`aReY,

]`T\WZ]V.aReYZ_W`LUZc_R^VN aReYZ_W`LSRdV_R^VN[`S, e`fTY]`T\WZ]V,

cf_Re]`hVdeacZ`cZej ac`TP_ZTV#!,

VdTRaVaReYdeYReRcVSVZ_XaRddVUe`dYV]]

Wc`^AReY.VdTRaVdYV]]RcXaReY, e`AReY.VdTRaVdYV]]RcXaReY^a$, TRccj`feeYVV_T`UZ_X

cVdf]e.dYV]]PViVT]R^VWc`^AReYe`AReY, ZWcVdf]el

ac`TVdd`c=`X4`_gVcdZ`_`WaReYcVdf]eVUZ_Vcc`cd+cVdf]e, n

V]dVl

ac`TVdd`c=`X4`_gVcdZ`_`WaReYe`>A$ZdT`^a]VeV, n

ViZe,

V_UZWcVRUje`V_T`UV n

V_UW`cVRTYhRgdRdaReY n

V_UZWhRgd n

442 C H A P T E R 2 2 ■ S A F E L Y E X E C U T I N G S Y S T E M C O M M A N D S

]ZS

Wf_TeZ`_ac`TVdd`c=`X^VddRXVl X]`SR]]`XaZU,

acVWZi.UReVcLaZUN, Wa.W`aV_]`XR,

WhcZeVWaacVWZi^VddRXVMcM_, WT]`dVWa,

n 0/

After checking that files do exist to encode, you check that they are not already in the process of being encoded by looking for a lockfile (an empty file with the name of the hRg file but the extension [`S), and then that the number of already-executing jobs does not exceed the limit set earlier. If the file is ready to encode, you create a lockfile and set the encoding job’s priority to as low as possible. Since you are going to have to pass a command to the shell, for security’s sake you make sure that the paths that are being passed are escaped properly with the VdTRaVdYV]]RcX function. You then send the job to the shell to be processed by the free LAME MP3 encoder (available as a package install for most distributions, and as a source code down- load at Yeea+ ]R^Vd`fcTVW`cXV_Ve U`h_]`RU U`h_]`RUYe^]), and you report the results.

Finally, in a library section at the end of the script, you define the ac`TVdd`c=`X function, which simply writes messages to a log file.

We can tell Tc`_ to execute the ^a$Ac`TVdd`caYa script once every minute by running Tc`_eRSV-fdVc_R^V/ to edit the appropriate Tc`_eRS file, where -fdVc_R^V/ is the UID of the user that should actually execute the script. To do this, add the following two lines to the Tc`_eRS file:

>2:=E@.j`fc_R^V1ViR^a]V_Ve

aReY e` aYa aReY e` ^a$Ac`TVdd`caYa

In a Tc`_eRS file, each entry consists of a periodicity specification and a command to be run for every period that matches the spec. The specification has five fields, corresponding to minute, hour, day of month, month, and day of week (! is Sunday, ' is Saturday), and those fields may be either values or wildcards that match the first occurrence of any other value. So the specification #! matches

• Any minute

• Any hour

• The 20th day of the month

• Any month

• Any day of the week

In other words, the specification will match the first occurrence of any day of the month numbered 20, which translates to midnight on the 20th of each month. Similarly, a specifica- tion like $!")"' will match only at 6:30 p.m. on June 1st.

SnyderSouthwell_5084C22.fm Page 442 Thursday, July 28, 2005 3:00 PM

If we use % as a day of the week, which matches Thursday, then the accompanying command will be executed only on the first Thursday on which all other values match. A spec- ification that is all wildcards, as in our Tc`_eRS entry just previously, will match every minute.

The other important thing to know about Tc`_eRS periodicity specifications is that a wild- card can be divided by some value; when this is done, the specification matches only when the remainder is 0 (that is, when the specification matches exactly). The specification &

will therefore match every five minutes.

Because the lockfile manages the task of keeping track of which jobs in the queue are already being handled by other scripts, Tc`_ is indeed the ideal way to safely start batch- processing scripts that do not require immediate processing. If a user knows she will have to wait half an hour for the results, waiting one extra minute for Tc`_ to begin the processing is trivial and even unnoticeable.

A PHP Batch-processing Daemon

When a user is expecting results that should take a second or two at most, waiting an extra minute for Tc`_ to start the batch-processing script is not reasonable at all. In this case you will need to write a daemon that will check the queue more often, every second if necessary, and create new child processes to handle jobs as resources become available.

Here then is an example of a daemon that watches for files that need ownership changes;

these are most commonly files uploaded by the notorious webserver user _`S`Uj (we discussed the security implications of this issue in Chapter 15). This code can be found also as

TYR_XV@h_VcdYZa5RV^`_aYa in the Chapter 22 folder of the downloadable archive of code for Pro PHP Security at Yeea+ hhhRacVddT`^.

-0aYa

dTYVUf]VdZX_R]d UVT]RcVeZT\d.", dVefadZX_R]YR_U]Vcd

aT_e]PdZX_R]D:8E6C>dZXPYR_U]Vc, aT_e]PdZX_R]D:89FAdZXPYR_U]Vc, ]`XWZ]V

]`X.TYR_XV@h_VcdYZa5RV^`_]`X, ^R\VdfcVhVcVc``e

ZWa`dZiPXVefZU.!l

ViZeTYR_XV@h_VcdYZa5RV^`_^fdeSVcf_Rdc``eMcM_, n

]Z^ZeaReYd

R]]`hVUAReYd.RccRj e^a Y`^V Td_jUVc fa]`RUd,

444 C H A P T E R 2 2 ■ S A F E L Y E X E C U T I N G S Y S T E M C O M M A N D S

UST`_WZX

USfdVc.fdVc_R^V, USaRdd.aRddh`cU, USY`de.]`TR]Y`de, US_R^V.aad,

TYR_XV@h_VcdYZa5RV^`_aYaT`_eZ_fVd

In its general outlines, this script is very similar to dZ^a]V5RV^`_5V^`aYa, which we presented and discussed in the section “A Demonstration Daemon.” For detailed discussion, you may want to turn back to our discussion there. In this first section of the script, you simply initialize necessary variables.

T`_eZ_fVdTYR_XV@h_VcdYZa5RV^`_aYa Z^a`ce[`SbfVfV^R_RXVcT]Rdd Z_T]fUVP`_TV[`S>R_RXVc4]RddaYa, TcVReVURV^`_

W`c\.aT_e]PW`c\, ZWW`c\..."l

ViZe4`f]U_`eW`c\McM_, n

V]dVZWW`c\l

dTcZaeViZed]VRgZ_XURV^`_cf__Z_X

ViZeDeRceVUSRT\Xc`f_UaVc^ZddZ`_d5RV^`_hZeYA:5W`c\McM_, n

URV^`_XVedZed`h_ac`TVdd:5 UaZU.a`dZiPXVeaZU,

URV^`_UVeRTYVdWc`^eYVT`_ec`]]Z_XeVc^Z_R]

ZWa`dZiPdVedZUl

U]`X5RV^`_T`f]U_`eUVeRTY, ViZe,

n

U]`X5RV^`_cf__Z_X,

]``aW`cVgVchReTYZ_XW`cbfVfVU[`Sd hYZ]VECF6l

d]VVaW`c&dVT`_UdVRTY]``a d]VVa&,

TYR_XV@h_VcdYZa5RV^`_aYaT`_eZ_fVd

In the next section of the script, you start the daemon running, detach it, and put it into an infi- nite hYZ]VECF6 loop, during which it wakes up every five seconds to check for a task that requires its attention.

SnyderSouthwell_5084C22.fm Page 444 Thursday, July 28, 2005 3:00 PM

T`_eZ_fVdTYR_XV@h_VcdYZa5RV^`_aYa UST`__VTeZ`_

US._Vh^jdb]ZUSY`deUSfdVcUSaRddUS_R^V, TcVReVR_Vh[`SbfVfV^R_RXVc`S[VTe

ecjl

[`S._Vh[`S>R_RXVcUS, n

TReTY6iTVaeZ`_Vl ViTVaeZ`_PYR_U]VcV, n

WVeTY_Vie`fedeR_UZ_X[`SZ_bfVfV hYZ]V[`S/_Viel

ecjl

[`S/deRce, n

TReTY6iTVaeZ`_Vl ViTVaeZ`_PYR_U]VcV, n

aRcdVcVbfVde

]ZdeT`^^R_U`h_VcaReY.Via]`UV[`S/cVbfVde, U]`XDeRceZ_X[`S[`S/ZU+T`^^R_U`h_VcaReY, TYVT\W`cT`^a]VeVTYR_XV@h_VcdYZacVbfVde

ZWT`^^R_U.TYR_XV@h_VcdYZammV^aej`h_VcmmV^aejaReYl [`S/cVdf]e.:_gR]ZUT`^^R_U,

[`S/deRefd.Vcc`c, n

TYVT\W`cgZ`]ReZ`_dZ_R]]`hVUaReY R]]`hVU.72=D6,

W`cVRTYR]]`hVUAReYd2DaReYaRcel ]``\W`c^ReTYRXRZ_deR]]`hVUaReYd

ZWdfSdecaReY!dec]V_aReYaRce..aReYaRcel R]]`hVU.ECF6,

ScVR\, n n

TYVT\R]d`W`cU`fS]VU`edZ_aReY ZWR]]`hVUmmdeca`daReYl [`S/cVdf]e.:_gR]ZUaReY,

[`S/deRefd.Vcc`c, n

446 C H A P T E R 2 2 ■ S A F E L Y E X E C U T I N G S Y S T E M C O M M A N D S

ZW_`Vcc`cdeYV_TRccj`fecVbfVde ZW[`S/deRefd.Vcc`cl dfTTVdd.1TY`h_aReY`h_Vc, ZWdfTTVddl

[`S/cVdf]e.4`f]U_`eTY`h_aReY`h_Vc, [`S/deRefd.Vcc`c,

n V]dVl

[`S/cVdf]e.@<, [`S/deRefd.U`_V, n

n

dRgV[`S ecjl

[`S/WZ_ZdY[`S/deRefd, n

TReTY6iTVaeZ`_Vl ViTVaeZ`_PYR_U]VcV, n

U]`X7Z_ZdYVU[`S[`S/ZU+[`S/deRefd, n

T]`dVUST`__VTeZ`_

US/T]`dV, f_dVeUSR_U[`S f_dVeUS[`S, ]`XVgVcjY`fc

ZWZddVe]Rde=`XmmUReVZ..!!

UReVY.]Rde=`Xl U]`XUReVc,

]Rde=`X.UReVY, n

V_UhYZ]VECF6]``a n

TYR_XV@h_VcdYZa5RV^`_aYaT`_eZ_fVd

This next section of the script demonstrates how this daemon handles the specific task that it is assigned to monitor, changing ownership of files. Every five seconds it wakes up, instantiates a new [`S>R_RXVc object, and looks for new additions to the queue. When it finds one, it parses the request into a command, owner ID, and path. It checks to ensure that the path is in a location that it, the daemon, is allowed to touch and is valid. If the path is correct, it uses the TY`h_ function to change the file’s ownership, logging its action, marking that queue entry as finished, and cleaning up. It also logs its presence every hour.

SnyderSouthwell_5084C22.fm Page 446 Thursday, July 28, 2005 3:00 PM

Một phần của tài liệu Pro PHP Security phần 9 pps (Trang 38 - 53)

Tải bản đầy đủ (PDF)

(53 trang)