﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-jojo's blog－－快乐忧伤都与你同在-文章分类-Linux 技术相关</title><link>http://www.blogjava.net/ruoyoux/category/34925.html</link><description>为梦想而来，为自由而生。
性情若水，风起水兴，风息水止，故时而激荡，时又清平……</description><language>zh-cn</language><lastBuildDate>Tue, 14 Jul 2009 11:42:08 GMT</lastBuildDate><pubDate>Tue, 14 Jul 2009 11:42:08 GMT</pubDate><ttl>60</ttl><item><title>每日一记 2009/07/09 Sed Command Tutorial/Example</title><link>http://www.blogjava.net/ruoyoux/articles/286084.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Thu, 09 Jul 2009 06:45:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/286084.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/286084.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/286084.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/286084.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/286084.html</trackback:ping><description><![CDATA[<div>
<h3>SED Tutorial</h3>
<ul>
    <li>The sed utility is an "editor"
    </li>
    <li>It is also noninteractive. This means you have to insert
    commands to be executed on the data at the command line or in a
    script to be processed.
    </li>
    <li>sed accepts a series of commands and executes them on a file
    (or set of files).</li>
    <li>sed fittingly stands for stream editor.
    </li>
    <li>It can be used to change all occurrences of "SAD" to "SED" or
    "New York" to "Newport."
    </li>
    <li>The stream editor is ideally suited to performing repetitive
    edits that would take considerable time if done manually.
    </li>
</ul>
<p>
<br />
How sed Works
</p>
<p>
The sed utility works by sequentially reading a file, line by line,
into memory. It then performs all actions specified for the line
and places the line back in memory to dump to the terminal with the
requested changes made. After all actions have taken place to this
one line, it reads the next line of the file and repeats the
process until it is finished with the file. As mentioned, the
default output is to display the contents of each line on the
screen. Two important factors come into play here—first, the
output can be redirected to another file to save the changes;
second, the original file, by default, is left unchanged. The
default is for sed to read the entire file and make changes to each
line within it. It can, however, be restricted to specified lines
as needed.
</p>
<p>
The syntax for the utility is:
</p>
<pre>sed [options] '{command}' [filename]<br />
<br />
</pre>
<p>
In this tutorial we will walk through the most commonly used commands
and options and illustrate how they work and where they would be
appropriate for use.
</p>
<p>
The Substitute Command
</p>
<p>
One of the most common uses of the sed utility, and any similar
editor, is to substitute one value for another. To accomplish this,
the syntax for the command portion of the operation is:
</p>
<pre>'s/{old value}/{new value}/'<br />
<br />
</pre>
<p>
Thus, the following illustrates how "lion" can be changed to
"eagle" very simply:
</p>
<pre>$ echo The lion group will meet on Tuesday after school | sed <br />
<br />
's/lion/eagle/'<br />
<br />
The eagle group will meet on Tuesday after school<br />
<br />
$<br />
<br />
</pre>
<p>
Notice that it is not necessary to specify a filename if input is
being derived from the output of a preceding command—the same
as is true for awk, sort, and most other LinuxUNIX command-line
utility programs.
</p>
<p>
Multiple Changes
</p>
<p>
If multiple changes need to be made to the same file or line, there
are three methods by which this can be accomplished. The first is
to use the "-e" option, which informs the program that more than
one editing command is being used. For example:
</p>
<pre>$ echo The lion group will meet on Tuesday after school | sed -e '<br />
<br />
s/lion/eagle/' -e 's/after/before/'<br />
<br />
The eagle group will meet on Tuesday before school<br />
<br />
$<br />
<br />
</pre>
<p>
This is pretty much the long way of going about it, and the "-e"
option is not commonly used to any great extent. A more preferable
way is to separate command with semicolons:
</p>
<pre>$ echo The lion group will meet on Tuesday after school | sed '<br />
<br />
s/lion/eagle/; s/after/before/'<br />
<br />
The eagle group will meet on Tuesday before school <br />
<br />
$<br />
<br />
</pre>
<p>
Notice that the semicolon must be the next character following the
slash. If a space is between the two, the operation will not
successfully complete and an error message will be returned. These
two methods are well and good, but there is one more method that
many administrators prefer. The key thing to note is that
everything between the two apostrophes (' ') is interpreted as sed
commands. The shell program reading in the commands will not assume
you are finished entering until the second apostrophe is entered.
This means that the command can be entered on multiple
lines—with Linux changing the prompt from PS1 to a
continuation prompt (usually "&gt;")—until the second
apostrophe is entered. As soon as it is entered, and Enter pressed,
the processing will take place and the same results will be
generated, as the following illustrates:
</p>
<pre>$ echo The lion group will meet on Tuesday after school | sed '<br />
<br />
&gt; s/lion/eagle/<br />
<br />
&gt; s/after/before/'<br />
<br />
The eagle group will meet on Tuesday before school<br />
<br />
$<br />
<br />
</pre>
<p>
Global Changes
</p>
<p>
Let's begin with a deceptively simple edit. Suppose the message
that is to be changed contains more than one occurrence of the item
to be changed. By default, the result can be different than what
was expected, as the following illustrates:
</p>
<pre>$ echo The lion group will meet this Tuesday at the same time<br />
<br />
as the meeting last Tuesday | sed 's/Tuesday/Thursday/'<br />
<br />
The lion group will meet this Thursday at the same time<br />
<br />
as the meeting last Tuesday <br />
<br />
$<br />
<br />
</pre>
<p>
Instead of changing every occurrence of "Tuesday" for "Thursday,"
the sed editor moves on after finding a change and making it,
without reading the whole line. The majority of sed commands
function like the substitute one, meaning they all work for the
first occurrence of the chosen sequence in each line. In order for
every occurrence to be substituted, in the event that more than one
occurrence appears in the same line, you must specify for the
action to take place globally:
</p>
<pre>$ echo The lion group will meet this Tuesday at the same time<br />
<br />
as the meeting last Tuesday | sed 's/Tuesday/Thursday/g'<br />
<br />
The lion group will meet this Thursday at the same time<br />
<br />
as the meeting last Thursday<br />
<br />
$<br />
<br />
</pre>
<p>
Bear in mind that this need for globalization is true whether the
sequence you are looking for consists of only one character or a
phrase.
</p>
<p>
sed can also be used to change record field delimiters from one to
another. For example, the following will change all tabs to spaces:
</p>
<pre>sed 's/	/ /g' <br />
<br />
</pre>
<p>
where the entry between the first set of slashes is a tab, while
the entry between the second set is a space. As a general rule, sed
can be used to change any printable character to any other
printable character. If you want to change unprintable characters
to printable ones—for example, a bell to the word
"bell"—sed is not the right tool for the job (but tr would
be).
</p>
<p>
Sometimes, you don't want to change every occurrence that appears
in a file. At times, you only want to make a change if certain
conditions are met—for example, following a match of some
other data. To illustrate, consider the following text file:
</p>
<pre>$ cat sample_one<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
Suppose that it would be desirable for "1" to be substituted with
"2," but only after the word "two" and not throughout every line.
This can be accomplished by specifying that a match is to be found
before giving the substitute command:
</p>
<pre>$ sed '/two/ s/1/2/' sample_one<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
two     2<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
And now, to make it even more accurate:
</p>
<pre>$ sed '<br />
<br />
&gt; /two/ s/1/2/<br />
<br />
&gt; /three/ s/1/3/' sample_one<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
$<br />
<br />
</pre>
<p>
Bear in mind once again that the only thing changed is the display.
If you look at the original file, it is the same as it always was.
You must save the output to another file to create permanence. It
is worth repeating that the fact that changes are not made to the
original file is a true blessing in disguise—it lets you
experiment with the file without causing any real harm, until you
get the right commands working exactly the way you expect and want
them to.
</p>
<p>
The following saves the changed output to a new file:
</p>
<pre>$ sed '<br />
<br />
&gt; /two/ s/1/2/<br />
<br />
&gt; /three/ s/1/3/' sample_one &gt; sample_two<br />
<br />
</pre>
<p>
The output file has all the changes incorporated in it that would
normally appear on the screen. It can now be viewed with head, cat,
or any other similar utility.
</p>
<p>
Script Files
</p>
<p>
The sed tool allows you to create a script file containing commands
that are processed from the file, rather than at the command line,
and is referenced via the "-f" option. By creating a script file,
you have the ability to run the same operations over and over
again, and to specify far more detailed operations than what you
would want to try to tackle from the command line each time.
</p>
<p>
Consider the following script file:
</p>
<pre>$ cat sedlist<br />
<br />
/two/ s/1/2/<br />
<br />
/three/ s/1/3/<br />
<br />
$<br />
<br />
</pre>
<p>
It can now be used on the data file to obtain the same results we
saw earlier:
</p>
<pre>$ sed -f sedlist sample_one<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
$<br />
<br />
</pre>
<p>
Notice that apostrophes are not used inside the source file, or
from the command line when the "-f" option is invoked. Script
files, also known as source files, are invaluable for operations
that you intend to repeat more than once and for complicated
commands where there is a possibility that you may make an error at
the command line. It is far easier to edit the source file and
change one character than to retype a multiple-line entry at the
command line.
</p>
<p>
Restricting Lines
</p>
<p>
The default is for the editor to look at, and for editing to take
place on, every line that is input to the stream editor. This can
be changed by specifying restrictions preceding the command. For
example, to substitute "1" with "2" only in the fifth and sixth
lines of the sample file's output, the command would be:
</p>
<pre>$ sed '5,6 s/1/2/' sample_one<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
two     2<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
In this case, since the lines to changes were specifically
specified, the substitute command was not needed. Thus you have the
flexibility of choosing which lines to changes (essentially,
restricting the changes) based upon matching criteria that can be
either line numbers or a matched pattern.
</p>
<p>
Prohibiting the Display
</p>
<p>
The default is for sed to display on the screen (or to a file, if
so redirected) every line from the original file, whether it is
affected by an edit operation or not; the "-n" parameter overrides
this action. "-n" overrides all printing and displays no lines
whatsoever, whether they were changed by the edit or not. For
example:
</p>
<pre>$ sed -n -f sedlist sample_one<br />
<br />
$<br />
<br />
<br />
<br />
$ sed -n -f sedlist sample_one &gt; sample_two<br />
<br />
$ cat sample_two<br />
<br />
$<br />
<br />
</pre>
<p>
In the first example, nothing is displayed on the screen. In the
second example, nothing is changed, and thus nothing is written to
the new file—it ends up being empty. Doesn't this negate the
whole purpose of the edit? Why is this useful? It is useful only
because the "-n" option has the ability to be overridden by a print
command (-p). To illustrate, suppose the script file were modified
to now resemble the following:
</p>
<pre>$ cat sedlist<br />
<br />
/two/ s/1/2/p<br />
<br />
/three/ s/1/3/p<br />
<br />
$<br />
<br />
</pre>
<p>
Then this would be the result of running it:
</p>
<pre>$ sed -n -f sedlist sample_one<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
two     2<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
$<br />
<br />
</pre>
<p>
Lines that stay the same as they were are not displayed at all.
Only the lines affected by the edit are displayed.  In this manner,
it is possible to pull those lines only, make the changes, and
place them in a separate file:
</p>
<pre>$ sed -n -f sedlist sample_one &gt; sample_two<br />
<br />
$<br />
<br />
<br />
<br />
$ cat sample_two<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
two     2<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
$<br />
<br />
</pre>
<p>
Another method of utilizing this is to print only a set number of
lines. For example, to print only lines two through six while
making no other editing changes:
</p>
<pre>$ sed -n '2,6p' sample_one<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
two     1<br />
<br />
$<br />
<br />
</pre>
<p>
All other lines are ignored, and only lines two through six are
printed as output. This is something remarkable that you cannot do
easily with any other utility. head will print the top of a file,
and tail will print the bottom, but sed allows you to pull anything
you want to from anywhere.
</p>
<p>
Deleting Lines
</p>
<p>
Substituting one value for another is far from the only function
that can be performed with a stream editor. There are many more
possibilities, and the second-most-used function in my opinion is
delete. Delete works in the same manner as substitute, only it
removes the specified lines (if you want to remove a word and not a
line, don't think of deleting, but think of substituting it for
nothing—<tt>s/cat//</tt>).
</p>
<p>
The syntax for the command is:
</p>
<pre>'{what to find} d'<br />
<br />
</pre>
<p>
To remove all of the lines containing "two" from the sample_one
file:
</p>
<pre>$ sed '/two/ d' sample_one<br />
<br />
one     1<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
To remove the first three lines from the display, regardless of
what they are:
</p>
<pre>$ sed '1,3 d' sample_one<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
Only the remaining lines are shown, and the first three cease to
exist in the display. There are several things to keep in mind with
the stream editor as they relate to global expressions in general,
and as they apply to deletions in particular:
</p>
<li> The up carat (^) signifies the beginning of a line, thus
<pre>sed '/^two/ d' sample_one<br />
<br />
</pre>
<p>
would only delete the line if "two" were the first three
characters of the line.
</p>
</li>
<li> The dollar sign ($) represents the end of the file, or the end
of a line, thus
<pre>sed '/two$/ d' sample_one<br />
<br />
</pre>
<p>
would delete the line only if "two" were the last three characters
of the line.
</p>
<p>
The result of putting these two together:
</p>
<pre>sed '/^$/ d' {filename}<br />
<br />
</pre>
<p>
deletes all blank lines from a file. For example, the following
substitutes "1" for "2" as well as "1" for "3" and removes any
trailing lines in the file:
</p>
<pre>$ sed '/two/ s/1/2/; /three/ s/1/3/; /^$/ d' sample_one<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
two     2<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
A common use for this is to delete a header. The following command
will delete all lines in a file, from the first line through to the
first blank line:
</p>
<pre>sed '1,/^$/ d' {filename}<br />
<br />
</pre>
<p>
Appending and Inserting Text
</p>
<p>
Text can be appended to the end of a file by using sed with the "a"
option. This is done in the following manner:
</p>
<pre>$ sed '$a<br />
<br />
&gt; This is where we stop<br />
<br />
&gt; the test' sample_one<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
This is where we stop<br />
<br />
the test<br />
<br />
$<br />
<br />
</pre>
<p>
Within the command, the dollar sign ($) signifies that the text is
to be appended to the end of the file. The backslashes () are
necessary to signify that a carriage return is coming. If they are
left out, an error will result proclaiming that the command is
garbled; anywhere that a carriage return is to be entered, you must
use the backslash.
</p>
<p>
To append the lines into the fourth and fifth positions instead of
at the end, the command becomes:
</p>
<pre>$ sed '3a<br />
<br />
&gt; This is where we stop<br />
<br />
&gt; the test' sample_one<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
This is where we stop<br />
<br />
the test<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
This appends the text after the third line. As with almost any
editor, you can choose to insert rather than append if you so
desire. The difference between the two is that append follows the
line specified, and insert starts with the line specified. When
using insert instead of append, just replace the "a" with an "i,"
as shown below:
</p>
<pre>$ sed '3i<br />
<br />
&gt; This is where we stop<br />
<br />
&gt; the test' sample_one<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
This is where we stop<br />
<br />
the test<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
two     1<br />
<br />
two     1<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
The new text appears in the middle of the output, and processing
resumes normally after the specified operation is carried out.
</p>
<p>
Reading and Writing Files
</p>
<p>
The ability to redirect the output has already been illustrated,
but it needs to be pointed out that files can be read in and
written out to simultaneously during operation of the editing
commands. For example, to perform the substitution and write the
lines between one and three to a file called sample_three:
</p>
<pre>$ sed '<br />
<br />
&gt; /two/ s/1/2/<br />
<br />
&gt; /three/ s/1/3/<br />
<br />
&gt; 1,3 w sample_three' sample_one<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
$<br />
<br />
<br />
<br />
$ cat sample_three<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
$<br />
<br />
</pre>
<p>
Only the lines specified are written to the new file, thanks to the
"1,3" specification given to the w (write) command. Regardless of
those written, all lines are displayed in the default output.
</p>
<p>
The Change Command
</p>
<p>
In addition to substituting entries, it is possible to change the
lines from one value to another. The thing to keep in mind is that
substitute works on a character-for-character basis, whereas change
functions like delete in that it affects the entire line:
</p>
<pre>$ sed '/two/ c<br />
<br />
&gt; We are no longer using two' sample_one<br />
<br />
one     1<br />
<br />
We are no longer using two<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
We are no longer using two<br />
<br />
We are no longer using two<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
Working much like substitute, the change command is greater in
scale—completely replacing the one entry for another,
regardless of character content, or context. At the risk of
overstating the obvious, when substitute was used, then only the
character "1" was replaced with "2," while when using change, the
entire original line was modified. In both situations, the match to
look for was simply the "two."
</p>
<p>
Change All but...
</p>
<p>
With most sed commands, the functions are spelled out as to what
changes are to take place. Using the exclamation mark, it is
possible to have the changes take place everywhere but those
specified—completely reversing the default operation.
</p>
<p>
For example, to delete all lines that contain the phrase "two," the
operation is:
</p>
<pre>$ sed '/two/ d' sample_one<br />
<br />
one     1<br />
<br />
three   1<br />
<br />
one     1<br />
<br />
three   1<br />
<br />
$<br />
<br />
</pre>
<p>
And to delete all lines except those that contain the phrase "two,"
the syntax becomes:
</p>
<pre>$ sed '/two/ !d' sample_one<br />
<br />
two     1<br />
<br />
two     1<br />
<br />
two     1<br />
<br />
$<br />
<br />
</pre>
<p>
If you have a file that contains a list of items and want to
perform an operation on each of the items in the file, then it is
important that you first do an intelligent scan of those entries
and think about what you are doing. To make matters easier, you can
do so by combining sed with any iteration routine (for, while,
until).
</p>
<p>
As an example, assume you have a text file named "animals" with the
following entries:
</p>
<p>
pig<br />
horse<br />
elephant<br />
cow<br />
dog<br />
cat
</p>
<p>
And you want to run the following routine:
</p>
<pre>#mcd.ksh<br />
<br />
for I in $*<br />
<br />
do<br />
<br />
echo Old McDonald had a $I<br />
<br />
echo E-I, E-I-O<br />
<br />
done<br />
<br />
</pre>
<p>
The result will be that each line is printed at the end of "Old
McDonald has a." While this is correct for the majority of the
entries, it is grammatically incorrect for the "elephant" entry, as
the result should be "an elephant" rather than "a elephant." Using
sed, you can scan the output from your shell file for such
grammatical errors and correct them on the fly, by first creating a
file of commands:
</p>
<pre>#sublist<br />
<br />
/ a a/ s/ a / an /<br />
<br />
/ a e/ s/ a / an /<br />
<br />
/a i/ s / a / an /<br />
<br />
/a o/ s/ a / an /<br />
<br />
/a u/ s/ a / an /<br />
<br />
</pre>
<p>
and then executing the process as follows:
</p>
<pre>$ sh mcd.ksh 'cat animals' | sed -f sublist  <br />
<br />
</pre>
<p>
Now, after the mcd script has been run, sed will scan the output
for anywhere that the single letter a (space, "a," space) is
followed by a vowel. If such exists, it will change the sequence to
space, "an," space. This corrects the problem before it ever prints
on the screen and ensures that editors everywhere sleep easier at
night. The result is:
</p>
<p>
Old McDonald had a pig<br />
E-I, E-I-O<br />
Old McDonald had a horse<br />
E-I, E-I-O<br />
Old McDonald had an elephant<br />
E-I, E-I-O<br />
Old McDonald had a cow<br />
E-I, E-I-O<br />
Old McDonald had a dog<br />
E-I, E-I-O<br />
Old McDonald had a cat<br />
E-I, E-I-O
</p>
<p>
Quitting Early
</p>
<p>
The default is for sed to read through an entire file and stop only
when the end is reached. You can stop processing early, however, by
using the quit command. Only one quit command can be specified, and
processing will continue until the condition calling the quit
command is satisfied.
</p>
<p>
For example, to perform substitution only on the first five lines
of a file and then quit:
</p>
<pre>$ sed '<br />
<br />
&gt; /two/ s/1/2/<br />
<br />
&gt; /three/ s/1/3/<br />
<br />
&gt; 5q' sample_one<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
$<br />
<br />
</pre>
<p>
The entry preceding the quit command can be a line number, as
shown, or a find/matching command like the following:
</p>
<pre>$ sed '<br />
<br />
&gt; /two/ s/1/2/<br />
<br />
&gt; /three/ s/1/3/<br />
<br />
&gt; /three/q' sample_one<br />
<br />
one     1<br />
<br />
two     2<br />
<br />
three   3<br />
<br />
$<br />
<br />
</pre>
<p>
You can also use the quit command to view lines beyond a standard
number and add functionality that exceeds those in head. For
example, the head command allows you to specify how many of the
first lines of a file you want to see—the default number is
ten, but any number can be used from one to ninety-nine. If you
want to see the first 110 lines of a file, you cannot do so with
head, but you can with sed:
</p>
<pre>sed 110q filename<br />
<br />
</pre>
<p>
Handling Problems
</p>
<p>
The main thing to keep in mind when dealing with sed is how it
works. It works by reading one line in, performing all the tasks it
knows to perform on that one line, and then moving on to the next
line. Each line is subjected to every editing command given.
</p>
<p>
This can be troublesome if the order of your operations is not
thoroughly thought out. For example, suppose you need to change all
"two" entries to "three" and all "three" to "four":
</p>
<pre>$ sed '<br />
<br />
&gt; /two/ s/two/three/<br />
<br />
&gt; /three/ s/three/four/' sample_one<br />
<br />
one     1<br />
<br />
four     1<br />
<br />
four   1<br />
<br />
one     1<br />
<br />
four     1<br />
<br />
four     1<br />
<br />
four   1<br />
<br />
$<br />
<br />
</pre>
<p>
The very first "two" read was changed to "three." It then meets the
criteria established for the next edit and becomes "four." The end
result is not what was wanted—there are now no entries but
"four" where there should be "three" and "four."
</p>
<p>
When performing such an operation, you must pay diligent attention
to the manner in which the operations are specified and arrange
them in an order in which one will not clobber another. For
example:
</p>
<pre>$ sed '<br />
<br />
&gt; /three/ s/three/four/<br />
<br />
&gt; /two/ s/two/three/' sample_one<br />
<br />
one     1<br />
<br />
three     1<br />
<br />
four   1<br />
<br />
one     1<br />
<br />
three     1<br />
<br />
three     1<br />
<br />
four   1<br />
<br />
$<br />
<br />
</pre>
<p>
This works perfectly, since the "three" value is changed prior to
"two" becoming "three."
</p>
<p>
Labels and Comments
</p>
<p>
Labels can be placed inside sed script files to make it easier to
explain what is transpiring, once the files begin to grow in size.
There are a variety of commands that relate to these labels, and
they include:
</p>
</li>
<li> : The colon signifies a label name. For example:
<pre>         :HERE<br />
<br />
</pre>
<p>
Labels beginning with the colon can be addressed by "b" and "t"
commands.
</p>
</li>
<li><tt>  b {label}</tt>  Works as a "goto" statement,
sending processing to the label preceded by a colon. For example,
<pre>    b HERE<br />
<br />
</pre>
<p>
sends processing to the line
</p>
<pre>    :HERE<br />
<br />
</pre>
<p>
If no label is specified following the b, processing goes to the
end of the script file.
</p>
</li>
<li><tt>  t {label}</tt>  Branches to the label only if
substitutions have been made since the last input line or execution
of a "t" command. As with "b," if a label name is not given,
processing moves to the end of the script file.</li>
<li><tt> #</tt>  The pound sign as the first character of a line
causes the entire line to be treated as a comment.  Comment lines
are different from labels and cannot be branched to with b or t
commands.</li>
</div>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/286084.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-07-09 14:45 <a href="http://www.blogjava.net/ruoyoux/articles/286084.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>每日一记 2009/06/16 Linux的时间设置与同步 (NTP)</title><link>http://www.blogjava.net/ruoyoux/articles/282655.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Tue, 16 Jun 2009 09:54:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/282655.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/282655.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/282655.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/282655.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/282655.html</trackback:ping><description><![CDATA[Network Time Protocol (NTP) 也是RHCE新增的考试要求. 学习的时候也顺便复习了一下如何设置Linux的时间,现在拿出来和大家分享<br />
设置NTP服务器不难但是NTP本身是一个很复杂的协议. 这里只是简要地介绍一下实践方法<br />
和上次一样,下面的实验都在RHEL5上运行<br />
<br />
<strong>1. 时间和时区</strong><br />
<br />
如果有人问你说现在几点? 你看了看表回答他说晚上8点了. 这样回答看上去没有什么问题,但是如果问你的这个人在欧洲的话那么你的回答就会让他很疑惑,因为他那里还太阳当空呢.<br />
<br />
这里就有产生了一个如何定义时间的问题.
因为在地球环绕太阳旋转的24个小时中,世界各地日出日落的时间是不一样的.所以我们才有划分时区(timezone)
的必要,也就是把全球划分成24个不同的时区. 所以我们可以把时间的定义理解为一个时间的值加上所在地的时区(注意这个所在地可以精确到城市)<br />
<br />
地理课上我们都学过格林威治时间(GMT), 它也就是0时区时间. 但是我们在计算机中经常看到的是UTC. 它是Coordinated
Universal Time的简写.
虽然可以认为UTC和GMT的值相等(误差相当之小),但是UTC已经被认定为是国际标准,所以我们都应该遵守标准只使用UTC<br />
<br />
那么假如现在中国当地的时间是晚上8点的话,我们可以有下面两种表示方式<br />
<br />
20:00 CST<br />
12:00 UTC<br />
<br />
这里的CST是Chinese Standard Time,也就是我们通常所说的北京时间了. 因为中国处在UTC+8时区,依次类推那么也就是12:00 UTC了.<br />
<br />
为什么要说这些呢(呵呵这里不是地理论坛吧...)? <br />
<br />
第一,不管通过任何渠道我们想要同步系统的时间,通常提供方只会给出UTC+0的时间值而不会提供时区(因为它不知道你在哪里).所以当我们设置系统时间的时候,设置好时区是首先要做的工作<br />
第二,很多国家都有夏令时(我记得小时候中国也实行过一次),那就是在一年当中的某一天时钟拨快一小时(比如从UTC+8一下变成UTC+9了),那么同理到时候还要再拨慢回来.如果我们设置了正确的时区,当需要改变时间的时候系统就会自动替我们调整<br />
<br />
现在我们就来看一下如何在Linux下设置时区,也就是time zone<br />
<br />
<br />
<strong>2. 如何设置Linux Time Zone</strong><br />
<br />
在Linux下glibc提供了我们事先编译好的许多timezone文件, 他们就放在/usr/share/zoneinfo这个目录下,这里基本涵盖了大部分的国家和城市<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 194px;">
<div dir="ltr" style="text-align: left;"># ls -F /usr/share/zoneinfo/<br />
<br />
Africa/      Chile/   Factory    Iceland      Mexico/   posix/      Universal<br />
<br />
America/     CST6CDT  GB         Indian/      Mideast/  posixrules  US/<br />
<br />
Antarctica/  Cuba     GB-Eire    Iran         MST       PRC         UTC<br />
<br />
Arctic/      EET      GMT        iso3166.tab  MST7MDT   PST8PDT     WET<br />
<br />
Asia/        Egypt    GMT0       Israel       Navajo    right/      W-SU<br />
<br />
Atlantic/    Eire     GMT-0      Jamaica      NZ        ROC         zone.tab<br />
<br />
Australia/   EST      GMT+0      Japan        NZ-CHAT   ROK         Zulu<br />
<br />
Brazil/      EST5EDT  Greenwich  Kwajalein    Pacific/  Singapore<br />
<br />
Canada/      Etc/     Hongkong   Libya        Poland    Turkey<br />
<br />
CET          Europe/  HST        MET          Portugal  UCT</div>
<br />
</pre>
</div>
在这里面我们就可以找到自己所在城市的time zone文件. 那么如果我们想查看对于每个time zone当前的时间我们可以用zdump命令<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 50px;">
<div dir="ltr" style="text-align: left;"># zdump Hongkong<br />
<br />
Hongkong  Fri Jul  6 06:13:57 2007 HKT</div>
<br />
</pre>
</div>
那么我们又怎么来告诉系统我们所在time zone是哪个呢? 方法有很多,这里举出两种<br />
<br />
第一个就是修改/etc/localtime这个文件,这个文件定义了我么所在的local time zone.<br />
我们可以在/usr/share/zoneinfo下找到我们的time zone文件然后拷贝去到/etc/localtimezone(或者做个symbolic link)<br />
<br />
假设我们现在的time zone是BST(也就是英国的夏令时间,UTC+1)<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 50px;">
<div dir="ltr" style="text-align: left;"># date<br />
<br />
Thu Jul  5 23:33:40 BST 2007</div>
<br />
</pre>
</div>
我们想把time zone换成上海所在的时区就可以这么做<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 66px;">
<div dir="ltr" style="text-align: left;"># ln -sf /usr/share/zoneinfo/posix/Asia/Shanghai /etc/localtime<br />
<br />
# date<br />
<br />
Fri Jul  6 06:35:52 CST 2007</div>
<br />
</pre>
</div>
这样时区就改过来了(注意时间也做了相应的调整)<br />
<br />
第二种方法也就设置TZ环境变量的值. 许多程序和命令都会用到这个变量的值. TZ的值可以有多种格式,最简单的设置方法就是使用tzselect命令<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 66px;">
<div dir="ltr" style="text-align: left;"># tzselect<br />
<br />
...<br />
<br />
TZ='America/Los_Angeles';export TZ</div>
<br />
</pre>
</div>
tzselect会让你选择所在的国家和城市(我省略了这些步骤),最后输出相应的TZ变量的值.那么如果你设置了TZ的值之后时区就又会发生变化<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 50px;">
<div dir="ltr" style="text-align: left;"># date<br />
<br />
Thu Jul  5 15:48:11 PDT 2007</div>
<br />
</pre>
</div>
通过这两个例子我们也可以发现TZ变量的值会override /etc/localtime.
也就是说当TZ变量没有定义的时候系统才使用/etc/localtime来确定time zone. 所以你想永久修改time
zone的话那么可以把TZ变量的设置写入/etc/profile里<br />
<br />
好了现在我们知道怎么设置时区了,下面我们就来看看如何设置Linux的时间吧<br />
<br />
<br />
<strong>3. Real Time Clock(RTC) and System Clock</strong><br />
<br />
说道设置时间这里还要明确另外一个概念就是在一台计算机上我们有两个时钟:一个称之为硬件时间时钟(RTC),还有一个称之为系统时钟(System Clock)<br />
<br />
硬件时钟是指嵌在主板上的特殊的电路, 它的存在就是平时我们关机之后还可以计算时间的原因<br />
系统时钟就是操作系统的kernel所用来计算时间的时钟. 它从1970年1月1日00:00:00 UTC时间到目前为止秒数总和的值 在Linux下系统时间在开机的时候会和硬件时间同步(synchronization),之后也就各自独立运行了<br />
<br />
那么既然两个时钟独自运行,那么时间久了必然就会产生误差了,下面我们来看一个例子<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 82px;">
<div dir="ltr" style="text-align: left;"># date<br />
<br />
Fri Jul  6 00:27:13 BST 2007<br />
<br />
# hwclock --show<br />
<br />
Fri 06 Jul 2007 12:27:17 AM BST  -0.968931 seconds</div>
<br />
</pre>
</div>
通过hwclock --show命令我们可以查看机器上的硬件时间(always in local time zone), 我们可以看到它和系统时间还是有一定的误差的, 那么我们就需要把他们同步<br />
<br />
如果我们想要把硬件时间设置成系统时间我们可以运行以下命令<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 34px;">
<div dir="ltr" style="text-align: left;"># hwclock --hctosys</div>
<br />
</pre>
</div>
反之,我们也可以把系统时间设置成硬件时间<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 34px;">
<div dir="ltr" style="text-align: left;"># hwclock --systohc</div>
<br />
</pre>
</div>
那么如果想设置硬件时间我们可以开机的时候在BIOS里设定.也可以用hwclock命令<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 34px;">
<div dir="ltr" style="text-align: left;"># hwclock --set --date="mm/dd/yy hh:mm:ss"</div>
<br />
</pre>
</div>
如果想要修改系统时间那么用date命令就最简单了<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 34px;">
<div dir="ltr" style="text-align: left;"># date -s "dd/mm/yyyy hh:mm:ss"</div>
<br />
</pre>
</div>
现在我们知道了如何设置系统和硬件的时间. 但问题是如果这两个时间都不准确了怎么办?
那么我们就需要在互联网上找到一个可以提供我们准确时间的服务器然后通过一种协议来同步我们的系统时间,那么这个协议就是NTP了.
注意接下去我们所要说的同步就都是指系统时间和网络服务器之间的同步了<br />
<br />
<strong><br />
4. 设置NTP Server前的准备</strong><br />
<br />
其实这个标题应该改为设置"NTP Relay Server"前的准备更加合适.
因为不论我们的计算机配置多好运行时间久了都会产生误差,所以不足以给互联网上的其他服务器做NTP Server.
真正能够精确地测算时间的还是原子钟. 但由于原子钟十分的昂贵,只有少部分组织拥有, 他们连接到计算机之后就成了一台真正的NTP Server.
而我们所要做的就是连接到这些服务器上同步我们系统的时间,然后把我们自己的服务器做成NTP Relay
Server再给互联网或者是局域网内的用户提供同步服务<br />
<br />
好了,前面讲了一大堆理论,现在我们来动手实践一下吧. 架设一个NTP Relay Server其实非常简单,我们先把需要的RPM包装上<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 34px;">
<div dir="ltr" style="text-align: left;"># rpm -ivh ntp-4.2.2p1-5.el5.rpm</div>
<br />
</pre>
</div>
那么第一步我们就要找到在互联网上给我们提供同步服务的NTP Server<br />
<br />
<a href="http://www.pool.ntp.org/" target="_blank">http://www.pool.ntp.org</a>是NTP的官方网站,在这上面我们可以找到离我们城市最近的NTP Server. NTP建议我们为了保障时间的准确性,最少找两个个NTP Server<br />
那么比如在英国的话就可以选择下面两个服务器<br />
<br />
0.uk.pool.ntp.org<br />
1.uk.pool.ntp.org<br />
<br />
它的一般格式都是number.country.pool.ntp.org<br />
<br />
第二步要做的就是在打开NTP服务器之前先和这些服务器做一个同步,使得我们机器的时间尽量接近标准时间. 这里我们可以用ntpdate命令<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 82px;">
<div dir="ltr" style="text-align: left;"># ntpdate 0.uk.pool.ntp.org<br />
<br />
6 Jul 01:21:49 ntpdate[4528]: step time server 213.222.193.35 offset -38908.575181 sec<br />
<br />
# ntpdate 0.pool.ntp.org<br />
<br />
6 Jul 01:21:56 ntpdate[4530]: adjust time server 213.222.193.35 offset -0.000065 sec</div>
<br />
</pre>
</div>
假如你的时间差的很离谱的话第一次会看到调整的幅度比较大,所以保险起见可以运行两次. 那么为什么在打开NTP服务之前先要手动运行同步呢? <br />
<br />
1. 因为根据NTP的设置,如果你的系统时间比正确时间要快的话那么NTP是不会帮你调整的,所以要么你把时间设置回去,要么先做一个手动同步<br />
2. 当你的时间设置和NTP服务器的时间相差很大的时候,NTP会花上较长一段时间进行调整.所以手动同步可以减少这段时间<br />
<br />
<br />
<strong>5. 配置和运行NTP Server</strong><br />
<br />
现在我们就来创建NTP的配置文件了, 它就是/etc/ntp.conf. 我们只需要加入上面的NTP Server和一个driftfile就可以了<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 82px;">
<div dir="ltr" style="text-align: left;"># vi /etc/ntp.conf<br />
<br />
server 0.uk.pool.ntp.org<br />
<br />
server 1.uk.pool.ntp.org<br />
<br />
driftfile /var/lib/ntp/ntp.drift</div>
<br />
</pre>
</div>
非常的简单. 接下来我们就启动NTP Server,并且设置其在开机后自动运行<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 50px;">
<div dir="ltr" style="text-align: left;"># /etc/init.d/ntpd/start<br />
<br />
# chkconfig --level 35 ntpd on</div>
<br />
</pre>
</div>
<br />
<strong>6. 查看NTP服务的运行状况</strong><br />
<br />
现在我们已经启动了NTP的服务,但是我们的系统时间到底和服务器同步了没有呢? 为此NTP提供了一个很好的查看工具: ntpq (NTP query)<br />
<br />
我建议大家在打开NTP服务器后就可以运行ntpq命令来监测服务器的运行.这里我们可以使用watch命令来查看一段时间内服务器各项数值的变化<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 130px;">
<div dir="ltr" style="text-align: left;"># watch ntpq -p<br />
<br />
Every 2.0s: ntpq -p                                  Sat Jul  7 00:41:45 2007<br />
<br />
<br />
<br />
remote           refid      st t when poll reach   delay   offset  jitter<br />
<br />
==============================================================================<br />
<br />
+193.60.199.75   193.62.22.98     2 u   52   64  377    8.578   10.203 289.032<br />
<br />
*mozart.musicbox 192.5.41.41      2 u   54   64  377   19.301  -60.218 292.411</div>
<br />
</pre>
</div>
现在我就来解释一下其中的含义<br />
<br />
remote: 它指的就是本地机器所连接的远程NTP服务器<br />
<br />
refid: 它指的是给远程服务器(e.g. 193.60.199.75)提供时间同步的服务器<br />
<br />
st: 远程服务器的级别. 由于NTP是层型结构,有顶端的服务器,多层的Relay Server再到客户端. 所以服务器从高到低级别可以设定为1-16. 为了减缓负荷和网络堵塞,原则上应该避免直接连接到级别为1的服务器的.<br />
<br />
t: 这个.....我也不知道啥意思^_^<br />
<br />
when: 我个人把它理解为一个计时器用来告诉我们还有多久本地机器就需要和远程服务器进行一次时间同步<br />
<br />
poll: 本地机和远程服务器多少时间进行一次同步(单位为秒). 在一开始运行NTP的时候这个poll值会比较小,那样和服务器同步的频率也就增加了,可以尽快调整到正确的时间范围.之后poll值会逐渐增大,同步的频率也就会相应减小<br />
<br />
reach: 这是一个八进制值,用来测试能否和服务器连接.每成功连接一次它的值就会增加<br />
<br />
delay: 从本地机发送同步要求到服务器的round trip time<br />
<br />
offset: 这是个最关键的值, 它告诉了我们本地机和服务器之间的时间差别. offset越接近于0,我们就和服务器的时间越接近<br />
<br />
jitter: 这是一个用来做统计的值. 它统计了在特定个连续的连接数里offset的分布情况. 简单地说这个数值的绝对值越小我们和服务器的时间就越精确<br />
<br />
那么大家细心的话就会发现两个问题: 第一我们连接的是0.uk.pool.ntp.org为什么和remote server不一样? 第二那个最前面的+和*都是什么意思呢?<br />
<br />
第一个问题不难理解,因为NTP提供给我们的是一个cluster server所以每次连接的得到的服务器都有可能是不一样.同样这也告诉我们了在指定NTP Server的时候应该使用hostname而不是IP<br />
<br />
第二个问题和第一个相关,既然有这么多的服务器就是为了在发生问题的时候其他的服务器还可以正常地给我们提供服务.那么如何知道这些服务器的状态呢? 这就是第一个记号会告诉我们的信息<br />
<br />
*<br />
它告诉我们远端的服务器已经被确认为我们的主NTP Server,我们系统的时间将由这台机器所提供<br />
<br />
+<br />
它将作为辅助的NTP Server和带有*号的服务器一起为我们提供同步服务. 当*号服务器不可用时它就可以接管<br />
<br />
-<br />
远程服务器被clustering algorithm认为是不合格的NTP Server<br />
<br />
x<br />
远程服务器不可用<br />
<br />
了解这些之后我们就可以实时监测我们系统的时间同步状况了<br />
<br />
<strong><br />
7. NTP安全设置</strong><br />
<br />
运行一个NTP Server不需要占用很多的系统资源,所以也不用专门配置独立的服务器,就可以给许多client提供时间同步服务, 但是一些基本的安全设置还是很有必要的<br />
那么这里一个很简单的思路就是第一我们只允许局域网内一部分的用户连接到我们的服务器. 第二个就是这些client不能修改我们服务器上的时间<br />
<br />
在/etc/ntp.conf文件中我们可以用restrict关键字来配置上面的要求<br />
<br />
首先我们对于默认的client拒绝所有的操作<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 34px;">
<div dir="ltr" style="text-align: left;">restrict default kod nomodify notrap nopeer noquery</div>
<br />
</pre>
</div>
然后允许本机地址一切的操作<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 34px;">
<div dir="ltr" style="text-align: left;">restrict 127.0.0.1</div>
<br />
</pre>
</div>
最后我们允许局域网内所有client连接到这台服务器同步时间.但是拒绝让他们修改服务器上的时间<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 34px;">
<div dir="ltr" style="text-align: left;">restrict 192.168.1.0 mask 255.255.255.0 nomodify</div>
<br />
</pre>
</div>
把这三条加入到/etc/ntp.conf中就完成了我们的简单配置. NTP还可以用key来做authenticaiton,这里就不详细介绍了<br />
<br />
<br />
<strong>8. NTP client的设置</strong><br />
<br />
做到这里我们已经有了一台自己的Relay
Server.如果我们想让局域网内的其他client都进行时间同步的话那么我们就都应该照样再搭建一台Relay
Server,然后把所有的client都指向这两台服务器(注意不要把所有的client都指向Internet上的服务器).
只要在client的ntp.conf加上这你自己的服务器就可以了<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 50px;">
<div dir="ltr" style="text-align: left;">server ntp1.leonard.com<br />
<br />
server ntp2.leonard.com</div>
<br />
</pre>
</div>
<strong><br />
9. 一些补充和拾遗</strong><br />
<br />
1. 配置文件中的driftfile是什么?<br />
我们每一个system clock的频率都有小小的误差,这个就是为什么机器运行一段时间后会不精确.
NTP会自动来监测我们时钟的误差值并予以调整.但问题是这是一个冗长的过程,所以它会把记录下来的误差先写入driftfile.这样即使你重新开机以
后之前的计算结果也就不会丢失了<br />
<br />
2. 如何同步硬件时钟?<br />
NTP一般只会同步system clock. 但是如果我们也要同步RTC的话那么只需要把下面的选项打开就可以了<br />
<br />
<div style="margin: 5px 20px 20px 0px;">
<div style="margin-bottom: 2px;">代码:</div>
<pre style="border: 1px solid #c6c6c6; margin: 0px; padding: 4px; overflow: auto; width: 640px; height: 50px;">
<div dir="ltr" style="text-align: left;"># vi /etc/sysconfig/ntpd<br />
<br />
SYNC_HWCLOCK=yes</div>
<br />
</pre>
</div>
<strong>10. 参考资料</strong><br />
<br />
1. <a href="http://www.freebsd.org/cgi/man.cgi?query=ntp.conf&amp;sektion=5" target="_blank">http://www.freebsd.org/cgi/man.cgi?q...conf&amp;sektion=5</a> <br />
不知为什么Redhat没有ntp.conf的man page.费了好大劲才从FreeBSD上找到了.<br />
<br />
2. <a href="http://www.eecis.udel.edu/%7Emills/ntp/html/index.html" target="_blank">http://www.eecis.udel.edu/~mills/ntp/html/index.html</a><br />
官方的NTP文档<br />
<br />
3. <a href="http://tldp.org/HOWTO/TimePrecision-HOWTO/index.html" target="_blank">http://tldp.org/HOWTO/TimePrecision-HOWTO/index.html</a><br />
The Linux Documentation Project上的NTP HOWTO<br />
<br />
4. <a href="http://www.pool.ntp.org/" target="_blank">www.pool.ntp.org/</a><br />
全球NTP服务器提供站<br />
<br />
<strong>11. 说明</strong><br />
<br />
顺便说一下, 大家也许会注意到标准时间的英文是Coordinated Universal Time, 为什么缩写会是UTC呢？<br />
<br />
在Wiki上给出的定论是英国人把它叫做Coordinated Universal Time。但是法语中它叫temps universel coordonn&#233;, 缩写也就是TUC.两个国家争执不休，最后妥协起见就把它叫做UTC了<br />
<br />
其实我看了挺有感触的。英语虽然是通用语言，但是问题在于现在很多核心技术全都掌握在老美手中，所以每有一个新名次都是会以英文来定义, 我觉得过多的英语依赖也是阻碍Linux在中国普及的一个因素. 要是中国能在新的领域有所突破的话也绝对可以起上自己的名字<br />
<br />
呵呵，乱说一通。只是想到有一天要是老外问我们北京时间英语怎么说的时候不知道会有多骄傲啊<br />
<img src ="http://www.blogjava.net/ruoyoux/aggbug/282655.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-06-16 17:54 <a href="http://www.blogjava.net/ruoyoux/articles/282655.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>每日一记 2009/06/06 linux服务器配置之Sendmail配置</title><link>http://www.blogjava.net/ruoyoux/articles/280353.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 06 Jun 2009 11:22:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/280353.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/280353.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/280353.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/280353.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/280353.html</trackback:ping><description><![CDATA[<strong>今天我们来配置一下简单的sendmail服务。。。呵呵、、、真的简单的配置。。。<br />
<br />
rpm&nbsp;-q&nbsp;sendmail<br />
<br />
还需安装这三个包<br />
&nbsp;sendmail-cf-8.12.8-4.i386<br />
<br />
&nbsp;sendmail-devel-8.12.8-4.i<br />
<br />
&nbsp;sendmail-doc-8.12.8-4.i38<br />
<br />
安装好后，我开始配置文件，，，，，<br />
<br />
修改/etc/mail/local-hosts-name文件<br />
[root@localhost&nbsp;named]#&nbsp;cat&nbsp;/etc/mail/local-host-names&nbsp;<br />
#&nbsp;local-host-names&nbsp;-&nbsp;include&nbsp;all&nbsp;aliases&nbsp;for&nbsp;your&nbsp;machine&nbsp;here.&nbsp;<br />
xuwini.com&nbsp;<br />
<br />
<br />
更改/etc/mail/sendmail.mc文件，修改下列地方：&nbsp;<br />
DaemonPortsOptions=Port=smtp,Addr=127.0.0.1,&nbsp;Name=MTA&nbsp;更改为：&nbsp;<br />
DaemonPortsOptions=Port=smtp,Addr=yourip或者0.0.0.0,&nbsp;Name=MTA&nbsp;<br />
然后m4&nbsp;/etc/mail/sendmail.mc&nbsp;&gt;&nbsp;/etc/mail/sendmail.cf&nbsp;<br />
<br />
<br />
修改&nbsp;/etc/rc.d/rc.local<br />
加入一行&nbsp;/usr/sbin/saslauthd&nbsp;-a&nbsp;shadow<br />
<br />
<br />
用户管理&nbsp;<br />
认证的配置：修改/etc/mail/sendmail.mc中的字段，取消&#8220;TRUST_AUTH_MECH&#8221;一行和下一行&#8220;define&#8221;处的注释。然后m4&nbsp;/etc/&nbsp;mail/sendmail.mc&gt;/etc/mail/sendmail.cf。&nbsp;<br />
[root@localhost&nbsp;named]#&nbsp;chkconfig&nbsp;--list&nbsp;saslauthd&nbsp;开启认证&nbsp;<br />
saslauthd&nbsp;0:off&nbsp;1:off&nbsp;2:off&nbsp;3:off&nbsp;4:off&nbsp;5:off&nbsp;6:off&nbsp;<br />
[root@localhost&nbsp;named]#&nbsp;chkconfig&nbsp;--level&nbsp;35&nbsp;saslauthd&nbsp;on&nbsp;<br />
<br />
<br />
建立用户帐号&nbsp;<br />
[root@localhost&nbsp;named]#&nbsp;groupadd&nbsp;mailuser&nbsp;<br />
[root@localhost&nbsp;named]#&nbsp;adduser&nbsp;-g&nbsp;mailuser&nbsp;-s&nbsp;/bin/bash&nbsp;xuwin&nbsp;<br />
[root@localhost&nbsp;named]#&nbsp;adduser&nbsp;-g&nbsp;mailuser&nbsp;-s&nbsp;/sbin/nologin&nbsp;xxx&nbsp;<br />
[root@localhost&nbsp;named]#&nbsp;passwd&nbsp;xuwin&nbsp;<br />
[root@localhost&nbsp;named]#&nbsp;passwd&nbsp;xxx&nbsp;密码都是123&nbsp;<br />
<br />
<br />
<br />
【修改/etc/aliases文件实现邮件转发和邮件列表：&nbsp;<br />
admin:&nbsp;xxx&nbsp;为邮件用户xxx设置别名admin&nbsp;<br />
testgroup:&nbsp;xuwin,xxx&nbsp;实现群发&nbsp;发给testgroup的邮件发给xuwin&nbsp;和&nbsp;xxx&nbsp;以上2个可以分别测试&nbsp;<br />
#newaliases&nbsp;】&nbsp;&nbsp;-------对于我们简单的邮件体系没什么大的用处，个人觉得<br />
<br />
<br />
<br />
访问控制设置&nbsp;<br />
更改/etc/mail/accesss文件，增加：&nbsp;<br />
[root@localhost&nbsp;named]#&nbsp;cat&nbsp;/etc/mail/access&nbsp;<br />
#&nbsp;Check&nbsp;the&nbsp;/usr/share/doc/sendmail/README.cf&nbsp;file&nbsp;for&nbsp;a&nbsp;description&nbsp;<br />
#&nbsp;of&nbsp;the&nbsp;format&nbsp;of&nbsp;this&nbsp;file.&nbsp;(search&nbsp;for&nbsp;access_db&nbsp;in&nbsp;that&nbsp;file)&nbsp;<br />
#&nbsp;The&nbsp;/usr/share/doc/sendmail/README.cf&nbsp;is&nbsp;part&nbsp;of&nbsp;the&nbsp;sendmail-doc&nbsp;<br />
#&nbsp;package.&nbsp;<br />
#&nbsp;<br />
#&nbsp;by&nbsp;default&nbsp;we&nbsp;allow&nbsp;relaying&nbsp;from&nbsp;localhost...&nbsp;<br />
localhost.localdomain&nbsp;RELAY&nbsp;<br />
localhost&nbsp;RELAY&nbsp;<br />
127.0.0.1&nbsp;RELAY&nbsp;<br />
xuwin.com&nbsp;RELAY&nbsp;<br />
完成后makemap&nbsp;hash&nbsp;/etc/mail/access.db&nbsp;&lt;&nbsp;/etc/mail/access进行数据库更新。<br />
<br />
<br />
#service&nbsp;sendmail&nbsp;restart&nbsp;<br />
<br />
已经成功进入。。。。<br />
我们试着来写一份简单的信。。。<br />
那么我在服务器上收信看看。。。。晕倒。。把密码打出啦。。。<br />
[root@localhost&nbsp;root]#&nbsp;telnet&nbsp;localhost&nbsp;25<br />
Trying&nbsp;127.0.0.1...<br />
Connected&nbsp;to&nbsp;localhost.<br />
Escape&nbsp;character&nbsp;is&nbsp;'^]'.<br />
220&nbsp;localhost.localdomain&nbsp;ESMTP&nbsp;Sendmail&nbsp;8.12.8/8.12.8;&nbsp;Sun,&nbsp;10&nbsp;Aug&nbsp;2008&nbsp;20:47:0<br />
6&nbsp;+0800<br />
mail&nbsp;from:&nbsp;root@xuwin.com<br />
250&nbsp;2.1.0&nbsp;root@xuwin.com...&nbsp;Sender&nbsp;ok<br />
rcpt&nbsp;to:&nbsp;xuwin@xuwin.com<br />
250&nbsp;2.1.5&nbsp;xuwin@xuwin.com...&nbsp;Recipient&nbsp;ok<br />
data<br />
354&nbsp;Enter&nbsp;mail,&nbsp;end&nbsp;with&nbsp;"."&nbsp;on&nbsp;a&nbsp;line&nbsp;by&nbsp;itself<br />
test<br />
hi.baidu.com/proxuwin<br />
xuwin.com<br />
.<br />
250&nbsp;2.0.0&nbsp;m7ACl6B7004271&nbsp;Message&nbsp;accepted&nbsp;for&nbsp;delivery<br />
quit<br />
221&nbsp;2.0.0&nbsp;localhost.localdomain&nbsp;closing&nbsp;connection<br />
Connection&nbsp;closed&nbsp;by&nbsp;foreign&nbsp;host.<br />
检查日志[root@localhost&nbsp;root]#&nbsp;tail&nbsp;/var/log/maillog<br />
<br />
你如果想在客户机上收发邮件，那么还需跟着我做。。呵呵。。。上面算是成功了，我们看看接下来会不会成功。。。。期待。。<br />
<br />
检测imap是否安装rpm&nbsp;-q&nbsp;imap<br />
安装rpm&nbsp;-ivh&nbsp;imap-*.rpm<br />
<br />
[root@localhost&nbsp;root]#&nbsp;chkconfig&nbsp;imap&nbsp;on<br />
[root@localhost&nbsp;root]#&nbsp;service&nbsp;xinetd&nbsp;restart<br />
停止&nbsp;xinetd：&nbsp;&nbsp;确定&nbsp;&nbsp;]<br />
启动&nbsp;xinetd：&nbsp;&nbsp;确定&nbsp;&nbsp;]<br />
[root@localhost&nbsp;root]#&nbsp;grep&nbsp;imap&nbsp;/etc/services<br />
imap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;143/tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imap2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Interim&nbsp;Mail&nbsp;Access&nbsp;Proto&nbsp;v2<br />
imap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;143/udp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imap2<br />
imap3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;220/tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Interactive&nbsp;Mail&nbsp;Access<br />
imap3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;220/udp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Protocol&nbsp;v3<br />
imaps&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;993/tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;IMAP&nbsp;over&nbsp;SSL<br />
imaps&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;993/udp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;IMAP&nbsp;over&nbsp;SSL<br />
<br />
有错误。。。那么就仔细检查一下，我们刚刚的配置<br />
看了一下，我把网络服务重启了一下。。不知道行不行。。。呵呵<br />
我们继续。。。。我估计是imap没配置好，因为可以发送的。。。。<br />
你们看。。。没出错。。完全是可行的。。。。这个就是我们刚刚发的。。。。<br />
。。。。功夫不负有心人&nbsp;啊。。找到原因了。。。呵呵。。&nbsp;/sbin/chkconfig&nbsp;imap&nbsp;on。。。。。。是imap没启动。。。晕倒。。。<br />
<br />
收到信了把。。。。<br />
<br />
当然我们不可能在一台服务器上那么瞎搞，一般都是两台两个域进行邮件交互。。。方法跟这个是一样的。。大家可以试试。。。呵呵。。。。<br />
<br />
教程到此，不好意思，浪费大家那么多的时间在找错误上。。。。</strong>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/280353.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-06-06 19:22 <a href="http://www.blogjava.net/ruoyoux/articles/280353.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Rsync命令参数详解</title><link>http://www.blogjava.net/ruoyoux/articles/279838.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 03 Jun 2009 08:36:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/279838.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/279838.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/279838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/279838.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/279838.html</trackback:ping><description><![CDATA[<div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Rsync</span><span style="font-size: 12pt; font-family: 宋体;">命令参数详解</span></div>
<div style="margin: 0cm 0cm 0pt; text-align: left;" align="left">&nbsp;</div>
<table border="0" cellpadding="0">
    <tbody>
        <tr>
            <td style="padding: 0.75pt; background-color: transparent;">
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在对rsync服务器配置结束以后，下一步就需要在客户端发出rsync命令来实现将服务器端的文件备份到客户端来。rsync是一个功能非常强大的工具，其命令也有很多功能特色选项，我们下面就对它的选项一一进行分析说明。Rsync的命令格式可以为以下六种：</span></div>
            <table style="border: 1pt outset black; width: 100%;" border="1" cellpadding="0" cellspacing="0" width="100%">
                <thead>
                    <tr>
                        <td style="padding: 3pt; background: #e6e6e6 none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 100%;" valign="top" width="100%">
                        <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　rsync [OPTION]... SRC DEST</span></div>
                        <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　rsync [OPTION]... SRC [USER@]HOST:DEST</span></div>
                        <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　rsync [OPTION]... [USER@]HOST:SRC DEST</span></div>
                        <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　rsync [OPTION]... [USER@]HOST::SRC DEST</span></div>
                        <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　rsync [OPTION]... SRC [USER@]HOST::DEST</span></div>
                        <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]</span></div>
                        </td>
                    </tr>
                </thead>
            </table>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　对应于以上六种命令格式，rsync有六种不同的工作模式：</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　1)拷贝本地文件。当SRC和DES路径信息都不包含有单个冒号":"分隔符时就启动这种工作模式。如：rsync -a /data /backup</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　2)使用一个远程shell程序(如rsh、ssh)来实现将本地机器的内容拷贝到远程机器。当DST路径地址包含单个冒号":"分隔符时启动该模式。如：rsync -avz *.c foo:src</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　3)使用一个远程shell程序(如rsh、ssh)来实现将远程机器的内容拷贝到本地机器。当SRC地址路径包含单个冒号":"分隔符时启动该模式。如：rsync -avz foo:src/bar /data</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　4)从远程rsync服务器中拷贝文件到本地机。当SRC路径信息包含"::"分隔符时启动该模式。如：rsync -av root@172.16.78.192::www /databack</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">　　5)从本地机器拷贝文件到远程rsync服务器中。当DST路径信息包含"::"分隔符时启动该模式。如：rsync -av /databack root@172.16.78.192::www</span></div>
            <div style="margin: 0cm 0cm 0pt; text-indent: 24pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">6)</span><span style="font-size: 12pt; font-family: 宋体;">列远程机的文件列表。这类似于rsync传输，不过只要在命令中省略掉本地机信息即可。如：rsync -v rsync://172.16.78.192/www</span></div>
            <div style="margin: 0cm 0cm 0pt; text-indent: 24pt; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">rsync</span><span style="font-size: 12pt; font-family: 宋体;">参数的具体解释如下：</span></div>
            <div style="margin: 0cm 0cm 0pt; background: #e6e6e6 none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">-v, --verbose </span><span style="font-size: 12pt; font-family: 宋体;">详细模式输出<br />
            -q, --quiet 精简输出模式<br />
            -c, --checksum 打开校验开关，强制对文件传输进行校验<br />
            -a, --archive 归档模式，表示以递归方式传输文件，并保持所有文件属性，等于-rlptgoD<br />
            -r, --recursive 对子目录以递归模式处理<br />
            -R, --relative 使用相对路径信息<br />
            -b, --backup 创建备份，也就是对于目的已经存在有同样的文件名时，将老的文件重新命名为~filename。可以使用--suffix选项来指定不同的备份文件前缀。<br />
            --backup-dir 将备份文件(如~filename)存放在在目录下。<br />
            -suffix=SUFFIX 定义备份文件前缀<br />
            -u, --update 仅仅进行更新，也就是跳过所有已经存在于DST，并且文件时间晚于要备份的文件。(不覆盖更新的文件)<br />
            -l, --links 保留软链结<br />
            -L, --copy-links 想对待常规文件一样处理软链结<br />
            --copy-unsafe-links 仅仅拷贝指向SRC路径目录树以外的链结<br />
            --safe-links 忽略指向SRC路径目录树以外的链结<br />
            -H, --hard-links 保留硬链结&nbsp;&nbsp;&nbsp;&nbsp; -p, --perms 保持文件权限<br />
            -o, --owner 保持文件属主信息&nbsp;&nbsp;&nbsp;&nbsp; -g, --group 保持文件属组信息<br />
            -D, --devices 保持设备文件信息&nbsp;&nbsp;&nbsp; -t, --times 保持文件时间信息<br />
            -S, --sparse 对稀疏文件进行特殊处理以节省DST的空间<br />
            -n, --dry-run现实哪些文件将被传输<br />
            -W, --whole-file 拷贝文件，不进行增量检测<br />
            -x, --one-file-system 不要跨越文件系统边界<br />
            -B, --block-size=SIZE 检验算法使用的块尺寸，默认是700字节<br />
            -e, --rsh=COMMAND 指定使用rsh、ssh方式进行数据同步<br />
            --rsync-path=PATH 指定远程服务器上的rsync命令所在路径信息<br />
            -C, --cvs-exclude 使用和CVS一样的方法自动忽略文件，用来排除那些不希望传输的文件<br />
            --existing 仅仅更新那些已经存在于DST的文件，而不备份那些新创建的文件<br />
            --delete 删除那些DST中SRC没有的文件<br />
            --delete-excluded 同样删除接收端那些被该选项指定排除的文件<br />
            --delete-after 传输结束以后再删除<br />
            --ignore-errors 及时出现IO错误也进行删除<br />
            --max-delete=NUM 最多删除NUM个文件<br />
            --partial 保留那些因故没有完全传输的文件，以是加快随后的再次传输<br />
            --force 强制删除目录，即使不为空<br />
            --numeric-ids 不将数字的用户和组ID匹配为用户名和组名<br />
            --timeout=TIME IP超时时间，单位为秒<br />
            -I, --ignore-times 不跳过那些有同样的时间和长度的文件<br />
            --size-only 当决定是否要备份文件时，仅仅察看文件大小而不考虑文件时间<br />
            --modify-window=NUM 决定文件是否时间相同时使用的时间戳窗口，默认为0<br />
            -T --temp-dir=DIR 在DIR中创建临时文件<br />
            --compare-dest=DIR 同样比较DIR中的文件来决定是否需要备份<br />
            -P 等同于 --partial<br />
            --progress 显示备份过程<br />
            -z, --compress 对备份的文件在传输时进行压缩处理<br />
            --exclude=PATTERN 指定排除不需要传输的文件模式<br />
            --include=PATTERN 指定不排除而需要传输的文件模式<br />
            --exclude-from=FILE 排除FILE中指定模式的文件<br />
            --include-from=FILE 不排除FILE指定模式匹配的文件<br />
            --version 打印版本信息<br />
            --address 绑定到特定的地址<br />
            --config=FILE 指定其他的配置文件，不使用默认的rsyncd.conf文件<br />
            --port=PORT 指定其他的rsync服务端口<br />
            --blocking-io 对远程shell使用阻塞IO<br />
            -stats 给出某些文件的传输状态<br />
            --progress 在传输时现实传输过程<br />
            --log-format=formAT 指定日志文件格式<br />
            --password-file=FILE 从FILE中得到密码<br />
            --bwlimit=KBPS 限制I/O带宽，KBytes per second&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -h, --help 显示帮助信息</span></div>
            </td>
        </tr>
    </tbody>
</table>
<div style="margin: 0cm 0cm 0pt;">&nbsp;</div>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/279838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-06-03 16:36 <a href="http://www.blogjava.net/ruoyoux/articles/279838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>每日一记 2009/06/03 screen处理后台任务 </title><link>http://www.blogjava.net/ruoyoux/articles/279817.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 03 Jun 2009 07:15:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/279817.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/279817.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/279817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/279817.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/279817.html</trackback:ping><description><![CDATA[<p>大家在起后台服务，或者长时间执行某个脚本的时候。</p>
<p>是不是感觉，交互性很差，</p>
<p>有时，想把结果直接在终端上输出，又怕不小心关闭了终端导致进程退出？ （有些sshd服务还会设置连接超时，自动退出终端）</p>
<p>现在用 <span style="color: rgb(0, 0, 255);"><strong>screen</strong>
</span>
这个指令可以很好的解决跑后台服务的尴尬。</p>
<p>命令其实超简单的：</p>
<p>直接在终端上输入 screen , 这个时候，服务器端会启一个新的终端，但这个终端，与之前的普通终端不一样，它不隶属于 sshd 进程组，这样，当本地终端关闭后，服务器终端不会被 kill。</p>
<p>当然，优点还不止这么些，在服务器终端里执行任务时，你甚至可以随时地切换到本地终端做些其他事情，然后，要回去时，再恢复到刚才已经打开的服务器终端里，如果刚才的任务没有结束，还可以继续执行任务。</p>
<p>操作步骤：</p>
<p>首先，进入 <strong><span style="color: rgb(0, 0, 255);">screen </span>
</strong>
-S sessionname终端。(sessionname是为了分辨你的session)</p>
<p>然后按 <strong><span style="color: rgb(0, 0, 255);">ctrl + a</span>
</strong>
，再按 <span style="color: rgb(0, 0, 255);"><strong>d</strong>
</span>
键暂时退出终端。</p>
<p>当要返回时， 先查看刚才的终端进程ID， <strong><span style="color: rgb(0, 0, 255);">screen -list</span>
</strong>
</p>
<p>或直接</p>
<p>&nbsp;<strong><span style="color: rgb(0, 0, 255);">screen -r xx</span>
</strong>
(刚才的sessionname)就可以了 </p>
<p>当然，当你开了很多个session后，打算关闭几个session，可以进入到session后，<strong><span style="color: rgb(0, 0, 255);">exit</span>
</strong>
一下就可以了.</p>
<p>总的来说， screen是可以完全替代 nohup 的，并且本身提供了较复杂的功能，但是我认为，刚才那些简单的功能足以应付日常运作。 </p>
<p>如果对该指令感兴趣的朋友，推荐一篇文章：</p>
<p><a href="http://www.ibm.com/developerworks/cn/linux/l-cn-screen/" target="_blank">http://www.ibm.com/developerworks/cn/linux/l-cn-screen/</a></p>
<p><br />
</p>
<p><br />
</p>
<p>补充：<br />
</p>
<p>A: secureCRT链接linux服务器时，网络断线了，但是服务器上的tty还没退出，我想重新连接到原来那个tty，可以做到么？<br />
<br />
B: 可以啊，你可以安装一个Screen，就可以享受他给你带来的方便了。<br />
<br />
A：如何创建一个虚拟shell环境？<br />
<br />
B：screen -S MyScr （其中&#8220;MyScr&#8221;是你为这个虚拟shell环境起的名字，可以自定义）<br />
输入回车之后，你就可以在这个虚拟的shell环境中工作了，你工作的内容都会被一直保留下来。试试吧，在里面敲几个命令，运行几个程序，和平常没有两样吧。<br />
<br />
A: 如何退出工作环境呢？<br />
<br />
B：如果想要退出要怎么办呢？只要按下Ctrl+A，然后按d，就可以退出刚刚建立的虚拟shell环境了（名字是MyScr）<br />
若干时间后，你又想继续刚才的工作了，只要再敲：<br />
screen -r MyScr<br />
就可以看到刚刚的界面了。怎么样，还是很简单适用的吧，呵呵。<br />
<br />
A: 可以不给他起名么？<br />
<br />
B：当然，你不给这个虚拟shell环境命名也是没问题的，如果只有一个虚拟环境的话，也可以这样用<br />
screen（回车）<br />
工作&#8230;&#8230;退出&#8230;&#8230;<br />
screen -r<br />
继续工作<br />
系统还会默认用PID号码表识screen虚拟的shell环境。<br />
例如，我直接用screen命令建立了一个虚拟环境，退出之后，我想查看虚拟环境的情况：<br />
<br />
A：如何察看当前有哪些Screen工作环境呢？<br />
<br />
B：screen -list<br />
输出应该是类似下面的：<br />
There is a screen on:<br />
25202.pts-1.firewallX (Detached)<br />
1 Socket in /tmp/screens/S-root.<br />
其中：<br />
&#8220;25202&#8221;是这个虚拟环境的PID。不信的话，可以ps查看一下，呵呵~<br />
&#8220;pts-1&#8221;是说你的ssh客户端登录的系统端口号是pts-1<br />
&#8220;firewallX&#8221;是我这台主机的名字<br />
如果你建立了很多虚拟环境，又没有为他们命名的话，就只能用PID来识别他们了。（记住这个PID号码太烦了吧，还是名字好！）<br />
例如，我现在有两个screen建立的虚拟环境，我输入：<br />
screen -list<br />
输出为：<br />
There are screens on:<br />
25202.pts-1.firewallX (Detached)<br />
25403.pts-1.firewallX (Detached)<br />
2 Sockets in /tmp/screens/S-root.<br />
那么，我如果想进入第二个虚拟环境的话，我可以用什么命令呢？答案如下：<br />
screen -r 25403<br />
<br />
A：如何创建新的screen呢？<br />
<br />
B：如果我登录进去之后，用ctrl-a c：再创建一个新的虚拟Shell环境，那么这个环境就是在PID为25403的虚拟环境里面的子虚拟环境。<br />
<br />
A：如何彻底退出一个screen工作环境呢？<br />
<br />
B：Ctrl-D<br />
<br />
A：如何在进入工作环境的时候就自动的运行screen呢？<br />
B：可以在~/.bash_profiler里最下面一行添加一句screen<br />
<br />
注意事项：关闭secureCRT之前，请先使用 Ctrl-D 退出screen
</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/279817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-06-03 15:15 <a href="http://www.blogjava.net/ruoyoux/articles/279817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>遍历两个日期之间天数的算法</title><link>http://www.blogjava.net/ruoyoux/articles/279347.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Mon, 01 Jun 2009 03:10:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/279347.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/279347.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/279347.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/279347.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/279347.html</trackback:ping><description><![CDATA[<p>package pkg.chart; <br />
<br />
import java.text.ParseException; <br />
import java.text.SimpleDateFormat; <br />
import java.util.Calendar; <br />
import java.util.Date; <br />
<br />
public class Test { <br />
public static void main(String[] args) throws ParseException { <br />
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); <br />
Long startM = sdf.parse("2009-1-14").getTime(); <br />
Long endM = sdf.parse("2010-1-14").getTime(); <br />
long result = (endM - startM) / (24 * 60 * 60 * 1000); <br />
System.out.println("差:" + result + "天"); <br />
<br />
Date startDate = sdf.parse("2009-01-14"); <br />
Calendar startTime = Calendar.getInstance(); <br />
startTime.clear(); <br />
startTime.setTime(startDate); <br />
for (int i = 0; i &lt; (int)result;i++) { <br />
String str = startTime.get(Calendar.YEAR) + "-" <br />
+ startTime.get(Calendar.MONTH) + "-" <br />
+ startTime.get(Calendar.DAY_OF_MONTH); <br />
System.out.println(str); <br />
startTime.add(Calendar.DAY_OF_YEAR, 1); <br />
} <br />
} <br />
}<br />
<br />
<br />
package demo;</p>
<p>import java.text.ParseException;<br />
import java.text.SimpleDateFormat;<br />
import java.util.Calendar;<br />
import java.util.Date;<br />
import java.util.GregorianCalendar;</p>
<p>/**<br />
&nbsp;* 遍历两个日期之间天数的算法<br />
&nbsp;* <br />
&nbsp;*/<br />
public class MyTest {<br />
&nbsp;public static void main(String[] args) throws ParseException {<br />
&nbsp;&nbsp;String start = "2007-01-27";<br />
&nbsp;&nbsp;String end = "2008-03-04";<br />
&nbsp;&nbsp;//字符串转换成日期<br />
&nbsp;&nbsp;SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");<br />
&nbsp;&nbsp;Date startDate=format.parse(start);<br />
&nbsp;&nbsp;Calendar startTime=Calendar.getInstance();<br />
&nbsp;&nbsp;startTime.clear();<br />
&nbsp;&nbsp;startTime.setTime(startDate);<br />
&nbsp;&nbsp;int startYear = startTime.get(Calendar.YEAR);<br />
&nbsp;&nbsp;int startMonth = startTime.get(Calendar.MONTH);<br />
&nbsp;&nbsp;int startDay = startTime.get(Calendar.DAY_OF_MONTH);<br />
&nbsp;&nbsp;Date endDate=format.parse(end);<br />
&nbsp;&nbsp;Calendar endTime=Calendar.getInstance();<br />
&nbsp;&nbsp;endTime.clear();<br />
&nbsp;&nbsp;endTime.setTime(endDate);<br />
&nbsp;&nbsp;int endYear = endTime.get(Calendar.YEAR);<br />
&nbsp;&nbsp;int endMonth = endTime.get(Calendar.MONTH);<br />
&nbsp;&nbsp;int endDay = endTime.get(Calendar.DAY_OF_MONTH);<br />
&nbsp;&nbsp;System.out.println("注意西方的月份从0到11，中国的月份从1到12");<br />
&nbsp;&nbsp;System.out.println("下面输入的是中国的日期.注意其中的转换问题");<br />
&nbsp;&nbsp;System.out.println("start date : " + start);<br />
&nbsp;&nbsp;System.out.println("end date : " + end);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;int count = 0;<br />
&nbsp;&nbsp;for (int x = startYear; x &lt;= endYear; x++) {<br />
&nbsp;&nbsp;&nbsp;//罗马历法产生年份公元1582年<br />
&nbsp;&nbsp;&nbsp;int gregorianCutoverYear = 1582;<br />
&nbsp;&nbsp;&nbsp;boolean isLeapYear = x &gt;= gregorianCutoverYear ? <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((x%4 == 0) &amp;&amp; ((x%100 != 0) || (x%400 == 0))) : <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(x%4 == 0);<br />
&nbsp;&nbsp;&nbsp;//判断是否是闰年<br />
&nbsp;&nbsp;&nbsp;//java方法<br />
&nbsp;&nbsp;&nbsp;//boolean isLeapYear = (new GregorianCalendar()).isLeapYear(x);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;String isBigYear = "是平年";<br />
&nbsp;&nbsp;&nbsp;if (isLeapYear) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;isBigYear = "是闰年";<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;System.out.println(x + "年" + isBigYear);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;//获取开始月的最大天数<br />
&nbsp;&nbsp;&nbsp;//java方法<br />
&nbsp;&nbsp;&nbsp;//SimpleDateFormat aFormat=new SimpleDateFormat("yyyy-MM-dd");<br />
&nbsp;&nbsp;&nbsp;//Date date = aFormat.parse(start);<br />
&nbsp;&nbsp;&nbsp;//Calendar time = Calendar.getInstance();<br />
&nbsp;&nbsp;&nbsp;//time.clear();<br />
&nbsp;&nbsp;&nbsp;//time.setTime(date);<br />
&nbsp;&nbsp;&nbsp;//int max=time.getActualMaximum(Calendar.DAY_OF_MONTH);//本月份的天数<br />
&nbsp;&nbsp;&nbsp;//System.out.println(max); <br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;//获取开始月的最大天数；大月是1，3，5，7，8，10，12；小月是4，6，9，11；特殊月是2<br />
&nbsp;&nbsp;&nbsp;int max = 0;<br />
&nbsp;&nbsp;&nbsp;if (startMonth == 1) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (isLeapYear) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = 29;<br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;if (!isLeapYear) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = 28;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;if (startMonth == 3 || startMonth == 5 || startMonth == 8 || startMonth == 10) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;max = 30;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;if (startMonth == 0 || startMonth == 2 || startMonth == 4 ||
startMonth == 6 || startMonth == 7 || startMonth == 9 || startMonth ==
11) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;max = 31;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;//循环每个月<br />
&nbsp;&nbsp;&nbsp;//如果在日期范围内月份循环时自增到了一年的最后一个月就将月份初始化到一月份<br />
&nbsp;&nbsp;&nbsp;int y = 0;<br />
&nbsp;&nbsp;&nbsp;//如果是开始日期的第一个年的月数就从开始月数循环<br />
&nbsp;&nbsp;&nbsp;if (x == startYear) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;y = startMonth;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;for (; y &lt; 12; y++) {&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//获取当月的最大天数；大月是1，3，5，7，8，10，12；小月是4，6，9，11；特殊月是2<br />
&nbsp;&nbsp;&nbsp;&nbsp;max = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (y == 1) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (isLeapYear) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = 29;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!isLeapYear) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = 28;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (y == 3 || y == 5 || y == 8 || y == 10) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = 30;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (y == 0 || y == 2 || y == 4 || y == 6 || y == 7 || y == 9 || y == 11) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = 31;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;int ty = y + 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(x + "年" + ty + "月");<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//循环每一天<br />
&nbsp;&nbsp;&nbsp;&nbsp;int z = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//如果是开始日期的第一个月的天数就从开始天数循环<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (x == startYear &amp;&amp; y == startMonth) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;z = startDay;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;for (; z &lt;= max; z++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( x + "年" + ty + "月" + z + "日");&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (x == endYear &amp;&amp; y == endMonth &amp;&amp; z == endDay) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;//如果已经遍历过了截至日期的最后月份就中止月份的循环<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (x == endYear &amp;&amp; y == endMonth) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;System.out.println(start + " 到 " + end + " 的天数差：" + count);<br />
&nbsp;&nbsp;<br />
&nbsp;}</p>
}
<img src ="http://www.blogjava.net/ruoyoux/aggbug/279347.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-06-01 11:10 <a href="http://www.blogjava.net/ruoyoux/articles/279347.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Memcache工作原理</title><link>http://www.blogjava.net/ruoyoux/articles/269403.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Thu, 07 May 2009 05:51:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/269403.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/269403.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/269403.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/269403.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/269403.html</trackback:ping><description><![CDATA[<h1 style="margin: 17pt 0cm 16.5pt 21.6pt;"><span style="font-family: Times New Roman;"><span style="font-size: x-large;"><span style="font-family: Times New Roman;"><span style="font-size: x-large;">&nbsp;1</span><span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: x-large;">Memcache</span></span><span style="font-size: x-large;">是什么</span></h1>
<p style="margin: 0cm 0cm 0pt 21.6pt; text-indent: 20.4pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">Memcache</span>是<span style="font-family: Times New Roman;">danga.com</span>的一个项目，最早是为<span style="font-family: Times New Roman;"> LiveJournal </span>服务的，目前全世界不少人使用这个缓存项目来构建自己大负载的网站，来分担数据库的压力。</span></p>
<p style="margin: 0cm 0cm 0pt 21.6pt;"><span style="font-size: small;">它可以应对任意多个连接，使用非阻塞的网络<span style="font-family: Times New Roman;">IO</span>。由于它的工作机制是在内存中开辟一块空间，然后建立一个<span style="font-family: Times New Roman;">HashTable</span>，<span style="font-family: Times New Roman;">Memcached</span>自管理这些<span style="font-family: Times New Roman;">HashTable</span>。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small; font-family: Times New Roman;">&nbsp;&nbsp;&nbsp; </span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">为什么会有<span style="font-family: Times New Roman;">Memcache</span>和<span style="font-family: Times New Roman;">memcached</span>两种名称？</span></p>
<p style="margin: 0cm 0cm 0pt 15.75pt; text-indent: 26.25pt;"><span style="font-size: small;">其实<span style="font-family: Times New Roman;">Memcache</span>是这个项目的名称，而<span style="font-family: Times New Roman;">memcached</span>是它服务器端的主程序文件名，</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp; &nbsp;</span></span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">Memcache</span>官方网站：<a href="http://www.danga.com/memcached"><span style="font-family: Times New Roman;">http://www.danga.com/memcached</span></a></span>，</p>
<h1 style="margin: 17pt 0cm 16.5pt 21.6pt;"><span style="font-family: Times New Roman;"><span style="font-size: x-large;">2<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: x-large;">Memcache</span></span><span style="font-size: x-large;">工作原理</span></h1>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt;"><span style="font-size: small;">首先<span style="font-family: Times New Roman;"> memcached </span>是以守护程序方式运行于一个或多个服务器中，随时接受客户端的连接操作，客户端可以由各种语言编写，目前已知的客户端<span style="font-family: Times New Roman;"> API </span>包括<span style="font-family: Times New Roman;"> Perl/PHP/Python/Ruby/Java/C#/C </span>等等。客户端在与<span style="font-family: Times New Roman;"> memcached </span>服务建立连接之后，接下来的事情就是存取对象了，每个被存取的对象都有一个唯一的标识符<span style="font-family: Times New Roman;"> key</span>，存取操作均通过这个<span style="font-family: Times New Roman;"> key </span>进行，保存到<span style="font-family: Times New Roman;"> memcached </span>中的对象实际上是放置内存中的，并不是保存在<span style="font-family: Times New Roman;"> cache </span>文件中的，这也是为什么<span style="font-family: Times New Roman;"> memcached </span>能够如此高效快速的原因。注意，这些对象并不是持久的，服务停止之后，里边的数据就会丢失。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt;"><span style="font-size: small;">与许多<span style="font-family: Times New Roman;"> cache </span>工具类似，<span style="font-family: Times New Roman;">Memcached </span>的原理并不复杂。它采用了<span style="font-family: Times New Roman;">C/S</span>的模式，在<span style="font-family: Times New Roman;"> server </span>端启动服务进程，在启动时可以指定监听的<span style="font-family: Times New Roman;"> ip</span>，自己的端口号，所使用的内存大小等几个关键参数。一旦启动，服务就一直处于可用状态。<span style="font-family: Times New Roman;">Memcached </span>的目前版本是通过<span style="font-family: Times New Roman;">C</span>实现，采用了单进程，单线程，异步<span style="font-family: Times New Roman;">I/O</span>，基于事件<span style="font-family: Times New Roman;"> (event_based) </span>的服务方式<span style="font-family: Times New Roman;">.</span>使用<span style="font-family: Times New Roman;"> libevent </span>作为事件通知实现。多个<span style="font-family: Times New Roman;"> Server </span>可以协同工作，但这些<span style="font-family: Times New Roman;"> Server </span>之间是没有任何通讯联系的，每个<span style="font-family: Times New Roman;"> Server </span>只是对自己的数据进行管理。<span style="font-family: Times New Roman;">Client </span>端通过指定<span style="font-family: Times New Roman;"> Server </span>端的<span style="font-family: Times New Roman;"> ip </span>地址<span style="font-family: Times New Roman;">(</span>通过域名应该也可以<span style="font-family: Times New Roman;">)</span>。需要缓存的对象或数据是以<span style="font-family: Times New Roman;"> key-&gt;value </span>对的形式保存在<span style="font-family: Times New Roman;">Server</span>端。<span style="font-family: Times New Roman;">key </span>的值通过<span style="font-family: Times New Roman;"> hash </span>进行转换，根据<span style="font-family: Times New Roman;"> hash </span>值把<span style="font-family: Times New Roman;"> value </span>传递到对应的具体的某个<span style="font-family: Times New Roman;"> Server </span>上。当需要获取对象数据时，也根据<span style="font-family: Times New Roman;"> key </span>进行。首先对<span style="font-family: Times New Roman;"> key </span>进行<span style="font-family: Times New Roman;"> hash</span>，通过获得的值可以确定它被保存在了哪台<span style="font-family: Times New Roman;"> Server </span>上，然后再向该<span style="font-family: Times New Roman;"> Server </span>发出请求。<span style="font-family: Times New Roman;">Client </span>端只需要知道保存<span style="font-family: Times New Roman;"> hash(key) </span>的值在哪台服务器上就可以了。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实说到底，memcache 的工作就是在专门的机器的内存里维护一张巨大的 hash 表，来存储经常被读写的一些数组与文件，从而极大的提高网站的运行效率。</p>
<h1 style="margin: 17pt 0cm 16.5pt 21.6pt;"><span style="font-family: Times New Roman;"><span style="font-size: x-large;">3<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: x-large;">如何使用</span></h1>
<ul>
    <li>
    <h1 style="margin: 17pt 0cm 16.5pt 21.6pt;">建立Manager类</h1>
    </li>
</ul>
<h1 style="margin: 17pt 0cm 16.5pt 21.6pt;"><span><span>&nbsp;&nbsp;
<div>
<div>
<div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=package%20com.alisoft.sme.memcached%3B%0A%0Aimport%20java.util.Date%3B%0A%0Aimport%20com.danga.MemCached.MemCachedClient%3B%0Aimport%20com.danga.MemCached.SockIOPool%3B%0A%0Apublic%20class%20MemCachedManager%20%7B%0A%0A%09%2F%2F%20%E5%88%9B%E5%BB%BA%E5%85%A8%E5%B1%80%E7%9A%84%E5%94%AF%E4%B8%80%E5%AE%9E%E4%BE%8B%0A%09protected%20static%20MemCachedClient%20mcc%20%3D%20new%20MemCachedClient()%3B%0A%0A%09protected%20static%20MemCachedManager%20memCachedManager%20%3D%20new%20MemCachedManager()%3B%0A%0A%09%2F%2F%20%E8%AE%BE%E7%BD%AE%E4%B8%8E%E7%BC%93%E5%AD%98%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E8%BF%9E%E6%8E%A5%E6%B1%A0%0A%09static%20%7B%0A%09%09%2F%2F%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%88%97%E8%A1%A8%E5%92%8C%E5%85%B6%E6%9D%83%E9%87%8D%0A%09%09String%5B%5D%20servers%20%3D%20%7B%20%22127.0.0.1%3A11211%22%20%7D%3B%0A%09%09Integer%5B%5D%20weights%20%3D%20%7B%203%20%7D%3B%0A%0A%09%09%2F%2F%20%E8%8E%B7%E5%8F%96socke%E8%BF%9E%E6%8E%A5%E6%B1%A0%E7%9A%84%E5%AE%9E%E4%BE%8B%E5%AF%B9%E8%B1%A1%0A%09%09SockIOPool%20pool%20%3D%20SockIOPool.getInstance()%3B%0A%0A%09%09%2F%2F%20%E8%AE%BE%E7%BD%AE%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BF%A1%E6%81%AF%0A%09%09pool.setServers(servers)%3B%0A%09%09pool.setWeights(weights)%3B%0A%0A%09%09%2F%2F%20%E8%AE%BE%E7%BD%AE%E5%88%9D%E5%A7%8B%E8%BF%9E%E6%8E%A5%E6%95%B0%E3%80%81%E6%9C%80%E5%B0%8F%E5%92%8C%E6%9C%80%E5%A4%A7%E8%BF%9E%E6%8E%A5%E6%95%B0%E4%BB%A5%E5%8F%8A%E6%9C%80%E5%A4%A7%E5%A4%84%E7%90%86%E6%97%B6%E9%97%B4%0A%09%09pool.setInitConn(5)%3B%0A%09%09pool.setMinConn(5)%3B%0A%09%09pool.setMaxConn(250)%3B%0A%09%09pool.setMaxIdle(1000%20*%2060%20*%2060%20*%206)%3B%0A%0A%09%09%2F%2F%20%E8%AE%BE%E7%BD%AE%E4%B8%BB%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%9D%A1%E7%9C%A0%E6%97%B6%E9%97%B4%0A%09%09pool.setMaintSleep(30)%3B%0A%0A%09%09%2F%2F%20%E8%AE%BE%E7%BD%AETCP%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%8C%E8%BF%9E%E6%8E%A5%E8%B6%85%E6%97%B6%E7%AD%89%0A%09%09pool.setNagle(false)%3B%0A%09%09pool.setSocketTO(3000)%3B%0A%09%09pool.setSocketConnectTO(0)%3B%0A%0A%09%09%2F%2F%20%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%9E%E6%8E%A5%E6%B1%A0%0A%09%09pool.initialize()%3B%0A%0A%09%09%2F%2F%20%E5%8E%8B%E7%BC%A9%E8%AE%BE%E7%BD%AE%EF%BC%8C%E8%B6%85%E8%BF%87%E6%8C%87%E5%AE%9A%E5%A4%A7%E5%B0%8F%EF%BC%88%E5%8D%95%E4%BD%8D%E4%B8%BAK%EF%BC%89%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E4%BC%9A%E8%A2%AB%E5%8E%8B%E7%BC%A9%0A%09%09mcc.setCompressEnable(true)%3B%0A%09%09mcc.setCompressThreshold(64%20*%201024)%3B%0A%09%7D%0A%0A%09%2F**%0A%09%20*%20%E4%BF%9D%E6%8A%A4%E5%9E%8B%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%EF%BC%8C%E4%B8%8D%E5%85%81%E8%AE%B8%E5%AE%9E%E4%BE%8B%E5%8C%96%EF%BC%81%0A%09%20*%20%0A%09%20*%2F%0A%09protected%20MemCachedManager()%20%7B%0A%0A%09%7D%0A%0A%09%2F**%0A%09%20*%20%E8%8E%B7%E5%8F%96%E5%94%AF%E4%B8%80%E5%AE%9E%E4%BE%8B.%0A%09%20*%20%0A%09%20*%20%40return%0A%09%20*%2F%0A%09public%20static%20MemCachedManager%20getInstance()%20%7B%0A%09%09return%20memCachedManager%3B%0A%09%7D%0A%0A%09%2F**%0A%09%20*%20%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E6%8C%87%E5%AE%9A%E7%9A%84%E5%80%BC%E5%88%B0%E7%BC%93%E5%AD%98%E4%B8%AD.%0A%09%20*%20%0A%09%20*%20%40param%20key%0A%09%20*%20%40param%20value%0A%09%20*%20%40return%0A%09%20*%2F%0A%09public%20boolean%20add(String%20key%2C%20Object%20value)%20%7B%0A%09%09return%20mcc.add(key%2C%20value)%3B%0A%09%7D%0A%0A%09public%20boolean%20add(String%20key%2C%20Object%20value%2C%20Date%20expiry)%20%7B%0A%09%09return%20mcc.add(key%2C%20value%2C%20expiry)%3B%0A%09%7D%0A%0A%09public%20boolean%20replace(String%20key%2C%20Object%20value)%20%7B%0A%09%09return%20mcc.replace(key%2C%20value)%3B%0A%09%7D%0A%0A%09public%20boolean%20replace(String%20key%2C%20Object%20value%2C%20Date%20expiry)%20%7B%0A%09%09return%20mcc.replace(key%2C%20value%2C%20expiry)%3B%0A%09%7D%0A%0A%09%2F**%0A%09%20*%20%E6%A0%B9%E6%8D%AE%E6%8C%87%E5%AE%9A%E7%9A%84%E5%85%B3%E9%94%AE%E5%AD%97%E8%8E%B7%E5%8F%96%E5%AF%B9%E8%B1%A1.%0A%09%20*%20%0A%09%20*%20%40param%20key%0A%09%20*%20%40return%0A%09%20*%2F%0A%09public%20Object%20get(String%20key)%20%7B%0A%09%09return%20mcc.get(key)%3B%0A%09%7D%0A%0A%09public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09%09MemCachedManager%20cache%20%3D%20MemCachedManager.getInstance()%3B%0A%09%09cache.add(%22hello%22%2C%20234)%3B%0A%09%09System.out.print(%22get%20value%20%3A%20%22%20%2B%20cache.get(%22hello%22))%3B%0A%09%7D%0A%7D%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol start="1">
    <li>package&nbsp;com.alisoft.sme.memcached;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.Date;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;com.danga.MemCached.MemCachedClient;&nbsp;&nbsp;</li>
    <li>import&nbsp;com.danga.MemCached.SockIOPool;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;MemCachedManager&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;创建全局的唯一实例&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;static&nbsp;MemCachedClient&nbsp;mcc&nbsp;=&nbsp;new&nbsp;MemCachedClient();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;static&nbsp;MemCachedManager&nbsp;memCachedManager&nbsp;=&nbsp;new&nbsp;MemCachedManager();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;设置与缓存服务器的连接池&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;服务器列表和其权重&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;servers&nbsp;=&nbsp;{&nbsp;"127.0.0.1:11211"&nbsp;};&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer[]&nbsp;weights&nbsp;=&nbsp;{&nbsp;3&nbsp;};&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;获取socke连接池的实例对象&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SockIOPool&nbsp;pool&nbsp;=&nbsp;SockIOPool.getInstance();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;设置服务器信息&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setServers(servers);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setWeights(weights);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;设置初始连接数、最小和最大连接数以及最大处理时间&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setInitConn(5);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setMinConn(5);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setMaxConn(250);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setMaxIdle(1000&nbsp;*&nbsp;60&nbsp;*&nbsp;60&nbsp;*&nbsp;6);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;设置主线程的睡眠时间&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setMaintSleep(30);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;设置TCP的参数，连接超时等&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setNagle(false);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setSocketTO(3000);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.setSocketConnectTO(0);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;初始化连接池&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool.initialize();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;压缩设置，超过指定大小（单位为K）的数据都会被压缩&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mcc.setCompressEnable(true);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mcc.setCompressThreshold(64&nbsp;*&nbsp;1024);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;保护型构造方法，不允许实例化！&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;MemCachedManager()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;获取唯一实例.&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;MemCachedManager&nbsp;getInstance()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;memCachedManager;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;添加一个指定的值到缓存中.&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;key&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;value&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;add(String&nbsp;key,&nbsp;Object&nbsp;value)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mcc.add(key,&nbsp;value);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;add(String&nbsp;key,&nbsp;Object&nbsp;value,&nbsp;Date&nbsp;expiry)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mcc.add(key,&nbsp;value,&nbsp;expiry);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;replace(String&nbsp;key,&nbsp;Object&nbsp;value)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mcc.replace(key,&nbsp;value);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;replace(String&nbsp;key,&nbsp;Object&nbsp;value,&nbsp;Date&nbsp;expiry)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mcc.replace(key,&nbsp;value,&nbsp;expiry);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;根据指定的关键字获取对象.&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;key&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Object&nbsp;get(String&nbsp;key)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mcc.get(key);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MemCachedManager&nbsp;cache&nbsp;=&nbsp;MemCachedManager.getInstance();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.add("hello",&nbsp;234);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print("get&nbsp;value&nbsp;:&nbsp;"&nbsp;+&nbsp;cache.get("hello"));&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package com.alisoft.sme.memcached;
import java.util.Date;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
public class MemCachedManager {
// 创建全局的唯一实例
protected static MemCachedClient mcc = new MemCachedClient();
protected static MemCachedManager memCachedManager = new MemCachedManager();
// 设置与缓存服务器的连接池
static {
// 服务器列表和其权重
String[] servers = { "127.0.0.1:11211" };
Integer[] weights = { 3 };
// 获取socke连接池的实例对象
SockIOPool pool = SockIOPool.getInstance();
// 设置服务器信息
pool.setServers(servers);
pool.setWeights(weights);
// 设置初始连接数、最小和最大连接数以及最大处理时间
pool.setInitConn(5);
pool.setMinConn(5);
pool.setMaxConn(250);
pool.setMaxIdle(1000 * 60 * 60 * 6);
// 设置主线程的睡眠时间
pool.setMaintSleep(30);
// 设置TCP的参数，连接超时等
pool.setNagle(false);
pool.setSocketTO(3000);
pool.setSocketConnectTO(0);
// 初始化连接池
pool.initialize();
// 压缩设置，超过指定大小（单位为K）的数据都会被压缩
mcc.setCompressEnable(true);
mcc.setCompressThreshold(64 * 1024);
}
/**
* 保护型构造方法，不允许实例化！
*
*/
protected MemCachedManager() {
}
/**
* 获取唯一实例.
*
* @return
*/
public static MemCachedManager getInstance() {
return memCachedManager;
}
/**
* 添加一个指定的值到缓存中.
*
* @param key
* @param value
* @return
*/
public boolean add(String key, Object value) {
return mcc.add(key, value);
}
public boolean add(String key, Object value, Date expiry) {
return mcc.add(key, value, expiry);
}
public boolean replace(String key, Object value) {
return mcc.replace(key, value);
}
public boolean replace(String key, Object value, Date expiry) {
return mcc.replace(key, value, expiry);
}
/**
* 根据指定的关键字获取对象.
*
* @param key
* @return
*/
public Object get(String key) {
return mcc.get(key);
}
public static void main(String[] args) {
MemCachedManager cache = MemCachedManager.getInstance();
cache.add("hello", 234);
System.out.print("get value : " + cache.get("hello"));
}
}
</pre>
</span></span></h1>
<h1 style="margin: 17pt 0cm 16.5pt 21.6pt;">&nbsp;建立数据对象</h1>
<span><span>
<div>
<div>
<div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=package%20com.alisoft.sme.memcached%3B%0A%0Aimport%20java.io.Serializable%3B%0A%0Apublic%20class%20TBean%20implements%20Serializable%20%7B%0A%09%0A%09private%20static%20final%20long%20serialVersionUID%20%3D%201945562032261336919L%3B%0A%0A%09private%20String%20name%3B%0A%0A%09public%20String%20getName()%20%7B%0A%09%09return%20name%3B%0A%09%7D%0A%0A%09public%20void%20setName(String%20name)%20%7B%0A%09%09this.name%20%3D%20name%3B%0A%09%7D%0A%7D%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol start="1">
    <li>package&nbsp;com.alisoft.sme.memcached;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;java.io.Serializable;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TBean&nbsp;implements&nbsp;Serializable&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;long&nbsp;serialVersionUID&nbsp;=&nbsp;1945562032261336919L;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;name;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getName()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;name;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setName(String&nbsp;name)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.name&nbsp;=&nbsp;name;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package com.alisoft.sme.memcached;
import java.io.Serializable;
public class TBean implements Serializable {
private static final long serialVersionUID = 1945562032261336919L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
</pre>
</span></span><span>
<div>
<div>
<div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%0A%3Cpre%20name%3D%22code%22%20class%3D%22java%22%3E%26nbsp%3B%3C%2Fpre%3E%0A%0A%3Ch2%20style%3D%22margin%3A%2013pt%200cm%2013pt%2028.8pt%3B%22%3E%3Cspan%20style%3D%22%22%20lang%3D%22EN-US%22%3E%3Cspan%20style%3D%22%22%3E%3Cspan%20style%3D%22font-family%3A%20'Times%20New%20Roman'%3B%22%3E%26nbsp%3B%26nbsp%3B%20%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3Cspan%20style%3D%22%22%3E%3Cspan%20style%3D%22font-size%3A%20large%3B%22%3E%E5%88%9B%E5%BB%BA%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fh2%3E%0A%3Ch2%20style%3D%22margin%3A%2013pt%200cm%2013pt%2028.8pt%3B%22%3E%26nbsp%3B%3C%2Fh2%3E%0A%3Cpre%20name%3D%22code%22%20class%3D%22java%22%3Epackage%20com.alisoft.sme.memcached.test%3B%0A%0Aimport%20junit.framework.TestCase%3B%0A%0Aimport%20org.junit.Test%3B%0A%0Aimport%20com.alisoft.sme.memcached.MemCachedManager%3B%0Aimport%20com.alisoft.sme.memcached.TBean%3B%0A%0Apublic%20class%20TestMemcached%20extends%20TestCase%20%7B%0A%0A%09private%20static%20MemCachedManager%20cache%3B%0A%0A%09%40Test%0A%09public%20void%20testCache()%20%7B%0A%09%09%0A%09%09TBean%20tb%20%3D%20new%20TBean()%3B%0A%09%09tb.setName(%22E%E7%BD%91%E6%89%93%E8%BF%9B%22)%3B%0A%09%09cache.add(%22bean%22%2C%20tb)%3B%0A%09%09%0A%09%09TBean%20tb1%20%3D%20(TBean)%20cache.get(%22bean%22)%3B%0A%09%09System.out.println(%22name%3D%22%20%2B%20tb1.getName())%3B%0A%09%09tb1.setName(%22E%E7%BD%91%E6%89%93%E8%BF%9B_%E4%BF%AE%E6%94%B9%E7%9A%84%22)%3B%0A%09%09%0A%09%09tb1%20%3D%20(TBean)%20cache.get(%22bean%22)%3B%0A%09%09System.out.println(%22name%3D%22%20%2B%20tb1.getName())%3B%0A%09%7D%0A%0A%09%40Override%0A%09protected%20void%20setUp()%20throws%20Exception%20%7B%0A%09%09super.setUp()%3B%0A%09%09cache%20%3D%20MemCachedManager.getInstance()%3B%0A%09%7D%0A%0A%09%40Override%0A%09protected%20void%20tearDown()%20throws%20Exception%20%7B%0A%09%09super.tearDown()%3B%0A%09%09cache%20%3D%20null%3B%0A%09%7D%0A%0A%7D%0A%3C%2Fpre%3E%0A%3Ch2%20style%3D%22margin%3A%2013pt%200cm%2013pt%2028.8pt%3B%22%3E%26nbsp%3B%3Cspan%20style%3D%22%22%3E%E6%B5%8B%E8%AF%95%E7%BB%93%E6%9E%9C%3C%2Fspan%3E%3C%2Fh2%3E%0A%3Ch2%20style%3D%22margin%3A%2013pt%200cm%2013pt%2028.8pt%3B%22%3E%3Cspan%20style%3D%22%22%3E%0A%3Cpre%20name%3D%22code%22%20class%3D%22java%22%3E%5BINFO%5D%20%2B%2B%2B%2B%20serializing%20for%20key%3A%20bean%20for%20class%3A%20com.alisoft.sme.memcached.TBean%0A%5BINFO%5D%20%2B%2B%2B%2B%20memcache%20cmd%20(result%20code)%3A%20add%20bean%208%200%2093%20(NOT_STORED)%0A%5BINFO%5D%20%2B%2B%2B%2B%20data%20not%20stored%20in%20cache%20for%20key%3A%20bean%0A%5BINFO%5D%20%2B%2B%2B%2B%20deserializing%20class%20com.alisoft.sme.memcached.TBean%0Aname%3DE%E7%BD%91%E6%89%93%E8%BF%9B%0A%5BINFO%5D%20%2B%2B%2B%2B%20deserializing%20class%20com.alisoft.sme.memcached.TBean%0Aname%3DE%E7%BD%91%E6%89%93%E8%BF%9B%0A%3C%2Fpre%3E%0A%26nbsp%3B%3C%2Fspan%3E%3C%2Fh2%3E%0A%20%20%20%20%20%20" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol start="1">
    <li>&lt;pre&nbsp;name="code"&nbsp;class="java"&gt;&nbsp;&lt;/pre&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&lt;h2&nbsp;style="margin:&nbsp;13pt&nbsp;0cm&nbsp;13pt&nbsp;28.8pt;"&gt;&lt;span&nbsp;style=""&nbsp;lang="EN-US"&gt;&lt;span&nbsp;style=""&gt;&lt;span&nbsp;style="font-family:&nbsp;'Times&nbsp;New&nbsp;Roman';"&gt;&nbsp;&nbsp;&nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&nbsp;style=""&gt;&lt;span&nbsp;style="font-size:&nbsp;large;"&gt;创建测试用例&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;&nbsp;&nbsp;</li>
    <li>&lt;h2&nbsp;style="margin:&nbsp;13pt&nbsp;0cm&nbsp;13pt&nbsp;28.8pt;"&gt;&nbsp;&lt;/h2&gt;&nbsp;&nbsp;</li>
    <li>&lt;pre&nbsp;name="code"&nbsp;class="java"&gt;package&nbsp;com.alisoft.sme.memcached.test;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;junit.framework.TestCase;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;org.junit.Test;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;com.alisoft.sme.memcached.MemCachedManager;&nbsp;&nbsp;</li>
    <li>import&nbsp;com.alisoft.sme.memcached.TBean;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestMemcached&nbsp;extends&nbsp;TestCase&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;MemCachedManager&nbsp;cache;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;@Test&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;testCache()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TBean&nbsp;tb&nbsp;=&nbsp;new&nbsp;TBean();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tb.setName("E网打进");&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.add("bean",&nbsp;tb);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TBean&nbsp;tb1&nbsp;=&nbsp;(TBean)&nbsp;cache.get("bean");&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("name="&nbsp;+&nbsp;tb1.getName());&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tb1.setName("E网打进_修改的");&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tb1&nbsp;=&nbsp;(TBean)&nbsp;cache.get("bean");&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("name="&nbsp;+&nbsp;tb1.getName());&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;setUp()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.setUp();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache&nbsp;=&nbsp;MemCachedManager.getInstance();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;tearDown()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.tearDown();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache&nbsp;=&nbsp;null;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&lt;/pre&gt;&nbsp;&nbsp;</li>
    <li>&lt;h2&nbsp;style="margin:&nbsp;13pt&nbsp;0cm&nbsp;13pt&nbsp;28.8pt;"&gt;&nbsp;&lt;span&nbsp;style=""&gt;测试结果&lt;/span&gt;&lt;/h2&gt;&nbsp;&nbsp;</li>
    <li>&lt;h2&nbsp;style="margin:&nbsp;13pt&nbsp;0cm&nbsp;13pt&nbsp;28.8pt;"&gt;&lt;span&nbsp;style=""&gt;&nbsp;&nbsp;</li>
    <li>&lt;pre&nbsp;name="code"&nbsp;class="java"&gt;[INFO]&nbsp;++++&nbsp;serializing&nbsp;for&nbsp;key:&nbsp;bean&nbsp;for&nbsp;class:&nbsp;com.alisoft.sme.memcached.TBean&nbsp;&nbsp;</li>
    <li>[INFO]&nbsp;++++&nbsp;memcache&nbsp;cmd&nbsp;(result&nbsp;code):&nbsp;add&nbsp;bean&nbsp;8&nbsp;0&nbsp;93&nbsp;(NOT_STORED)&nbsp;&nbsp;</li>
    <li>[INFO]&nbsp;++++&nbsp;data&nbsp;not&nbsp;stored&nbsp;in&nbsp;cache&nbsp;for&nbsp;key:&nbsp;bean&nbsp;&nbsp;</li>
    <li>[INFO]&nbsp;++++&nbsp;deserializing&nbsp;class&nbsp;com.alisoft.sme.memcached.TBean&nbsp;&nbsp;</li>
    <li>name=E网打进&nbsp;&nbsp;</li>
    <li>[INFO]&nbsp;++++&nbsp;deserializing&nbsp;class&nbsp;com.alisoft.sme.memcached.TBean&nbsp;&nbsp;</li>
    <li>name=E网打进&nbsp;&nbsp;</li>
    <li>&lt;/pre&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&lt;/span&gt;&lt;/h2&gt;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
    </li>
</ol>
</div>
</span>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/269403.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-05-07 13:51 <a href="http://www.blogjava.net/ruoyoux/articles/269403.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Mencache Introduction</title><link>http://www.blogjava.net/ruoyoux/articles/269402.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Thu, 07 May 2009 05:50:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/269402.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/269402.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/269402.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/269402.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/269402.html</trackback:ping><description><![CDATA[<h2>What is <tt>memcached</tt>?</h2>
<p><tt>memcached</tt> is a high-performance, distributed
memory object caching system, generic in nature, but intended for use
in speeding up dynamic web applications by alleviating database load.</p>
<p><a href="http://www.danga.com/">Danga Interactive</a> developed <tt>memcached</tt> to enhance the speed of <a href="http://www.livejournal.com/">LiveJournal.com</a>,
a site which was already doing 20 million+ dynamic page views per day
for 1 million users with a bunch of webservers and a bunch of database
servers. <tt>memcached</tt> dropped the database load to
almost nothing, yielding faster page load times for users, better
resource utilization, and faster access to the databases on a memcache
miss.</p>
<h2>How it Works</h2>
<p>First, you start up the <tt>memcached</tt> daemon on as
many spare machines as you have. The daemon has no configuration file,
just a few command line options, only 3 or 4 of which you'll likely
use:
</p>
<pre># ./memcached -d -m 2048 -l 10.0.0.40 -p 11211</pre>
<p>This starts <tt>memcached</tt> up as a daemon, using 2GB
of memory, and listening on IP 10.0.0.40, port 11211. Because a 32-bit
process can only address 4GB of virtual memory (usually significantly
less, depending on your operating system), if you have a 32-bit server
with 4-64GB of memory using PAE you can just run multiple processes on
the machine, each using 2 or 3GB of memory.</p>
<h2>Porting the Application</h2>
<p>Now, in your application, wherever you go to do a database query,
first check the memcache. If the memcache returns an undefined object,
then go to the database, get what you're looking for, and put it in the
memcache:</p>
<pre>
<div>Perl Example (see <a href="http://www.danga.com/memcached/apis.bml">APIs page</a>)</div>
<br />
sub get_foo_object {<br />
my $foo_id = int(shift);<br />
my $obj = $::MemCache-&gt;get("foo:$foo_id");<br />
return $obj if $obj;<br />
<br />
$obj = $::db-&gt;selectrow_hashref("SELECT .... FROM foo f, bar b ".<br />
"WHERE ... AND f.fooid=$foo_id");<br />
$::MemCache-&gt;set("foo:$foo_id", $obj);<br />
return $obj;<br />
}</pre>
<p>(If your internal API was already clean enough, you should only have
to do this in a few spots. Start with the queries that kill your
database the most, then move to doing as much as possible.)</p>
<p>You'll notice the data structure the server provides is just a
dictionary. You assign values to keys, and you request values from keys.</p>
<p>Now, what actually happens is that the API hashes your key to a
unique server. (You define all the available servers and their
weightings when initializing the API) Alternatively, the APIs also let
you provide your own hash value. A good hash value for user-related
data is the user's ID number. Then, the API maps that hash value onto a
server (modulus number of server buckets, one bucket for each server
IP/port, but some can be weighted heigher if they have more memory
available).</p>
<p>If a host goes down, the API re-maps that dead host's requests onto the servers that are available.</p>
<h2>Shouldn't the database do this?</h2>
<p>Regardless of what database you use (MS-SQL, Oracle, Postgres, MySQL-InnoDB, etc..), there's a lot of overhead in implementing <a href="http://www.wikipedia.org/wiki/ACID">ACID</a>
properties in a RDBMS, especially when disks are involved, which means
queries are going to block. For databases that aren't ACID-compliant
(like MySQL-MyISAM), that overhead doesn't exist, but reading threads
block on the writing threads.</p>
<p><tt>memcached</tt> never blocks.  See the "Is memcached fast?" question below.</p>
<h2>What about shared memory?</h2>
<p>The first thing people generally do is cache things within their
web processes.  But this means your cache is duplicated multiple
times, once for each mod_perl/PHP/etc thread.  This is a waste of
memory and you'll get low cache hit rates.  If you're using a
multi-threaded language or a shared memory API (IPC::Shareable, etc),
you can have a global cache for all threads, but it's per-machine.  It doesn't scale to multiple machines.
Once you have 20 webservers, those 20 independent caches start to look
just as silly as when you had 20 threads with their own caches on a
single box.  (plus, shared memory is typically laden with limitations)</p>
<p>The <tt>memcached</tt> server and clients work together to implement one
global cache across as many machines as you have.  In fact, it's
recommended you run both web nodes (which are typically memory-lite
and CPU-hungry) and memcached processes (which are memory-hungry and
CPU-lite) on the same machines.  This way you'll save network
ports.</p>
<h2>What about MySQL 4.x query caching?</h2>
<p>MySQL query caching is less than ideal, for a number of reasons:</p>
<ul>
    <li>MySQL's query cache destroys the entire cache for a given table
    whenever that table is changed. On a high-traffic site with updates
    happening many times per second, this makes the the cache practically
    worthless. In fact, it's often harmful to have it on, since there's a
    overhead to maintain the cache.</li>
    <li>On 32-bit architectures, the entire server (including the query cache) is limited to a 4 GB virtual address space.  <tt>memcached</tt> lets you run as many processes as you want, so you have no limit on memory cache size.</li>
    <li>MySQL has a query cache, not an object cache. If your objects
    require extra expensive construction after the data retrieval step,
    MySQL's query cache can't help you there.</li>
</ul>
<p>If the data you need to cache is small and you do infrequent updates, MySQL's query caching should work for you.  If not, use <tt>memcached</tt>.</p>
<h2>What about database replication?</h2>
<p>You can spread your reads with replication, and that helps a lot,
but you can't spread writes (they have to process on all machines) and
they'll eventually consume all your resources.  You'll find yourself
adding replicated slaves at an ever-increasing rate to make up for the
diminishing returns each additional slave provides.</p>
<p>The next logical step is to horizontally partition your dataset
onto different master/slave clusters so you can spread your writes,
and then teach your application to connect to the correct cluster
depending on the data it needs.</p>
<p>While this strategy works, and is recommended, more databases (each
with a bunch of disks) statistically leads to more frequent hardware
failures, which are annoying.</p>
<p>With <tt>memcached</tt> you can reduce your database reads to a mere
fraction, leaving the databases to mainly do infrequent writes, and
end up getting much more bang for your buck, since your databases
won't be blocking themselves doing ACID bookkeeping or waiting on
writing threads.</p>
<h2>Is <tt>memcached</tt> fast?</h2>
<p>Very fast.  It uses <a href="http://www.monkey.org/%7Eprovos/libevent/">libevent</a> to scale
to any number of open connections (using <a href="http://www.xmailserver.org/linux-patches/nio-improve.html">epoll</a>
on Linux, if available at runtime), uses non-blocking network I/O, refcounts internal objects
(so objects can be in multiple states to multiple clients), and uses
its own slab allocator and hash table so virtual memory never gets
externally fragmented and allocations are guaranteed O(1).</p>
<h2>What about race conditions?</h2>
<p>You might wonder: <em>"What if the <tt>get_foo()</tt> function adds a
stale version of the Foo object to the cache right as/after the user
updates their Foo object via update_foo()?"</em></p>
<p>While the server and API only have one way to get data from the cache, there exists 3 ways to put data in:</p>
<ul>
    <li><strong>set</strong> -- unconditionally sets a given key with a given value (<tt>update_foo()</tt> should use this)</li>
    <li><strong>add</strong> -- adds to the cache, only if it doesn't already exist (<tt>get_foo()</tt> should use this)</li>
    <li><strong>replace</strong> -- sets in the cache only if the key already exists (not as useful, only for completeness)</li>
</ul>
Additionally, all three support an expiration time.
<img src ="http://www.blogjava.net/ruoyoux/aggbug/269402.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-05-07 13:50 <a href="http://www.blogjava.net/ruoyoux/articles/269402.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>how to monitor ibm mq from nagios</title><link>http://www.blogjava.net/ruoyoux/articles/269254.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 06 May 2009 07:51:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/269254.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/269254.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/269254.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/269254.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/269254.html</trackback:ping><description><![CDATA[<p>This was one of the search terms that found an
article here&#8230; I hadn&#8217;t addressed this directly, but I use Nagios to
monitor my company&#8217;s server environment, and specifically implemented
that monitoring for IBM Websphere MQ. </p>
<p>For MQ, I run nagios monitoring against queue depth and processes. I
installed three plugins to run against WebSphere. Of these one was
developed for my company&#8217;s needs (qdepth), one was changed slightly
(channels) and the last debugged, found not to actually measure
accurately, and not resolved (message age). </p>
<p>Here&#8217;s the nagios console for the websphere MQ server. &#8220;message age&#8221;
in the second qdepth check service title is deceptive - actually
checking qdepth&#8230;</p>
<p><a href="http://dougmunsinger.com/images/posts/2008/nagios.png" rel="shadowbox[post-546];player=img;" title="websphere MQ nagios server result"><img src="http://dougmunsinger.com/images/posts/2008/nagios_400.png" title="nagios" alt="nagios" /></a></p>
<p>This is the commands section from the nrpe.cfg file on the WebSphere MQ server. </p>
<p><code><br />
command[check_mq_channel]=/usr/local/nagios/libexec/check_mq_channel.sh $ARG1$ $ARG2$<br />
command[check_mq_msgage]=/usr/local/nagios/libexec/check_mq_msgage.sh $ARG1$ $ARG2$ $ARG3$ $ARG4$<br />
command[wmq_check_qdepth]=/usr/local/nagios/libexec/wmq_check_qdepth.pl $ARG1$ $ARG2$ $ARG3$<br />
</code></p>
<p>Of these we only really using qdepth monitoring. The channels come
up triggered, so an inactive state is fine, and the plugin as written
only tests for &#8220;running&#8221;. The message age plugin, as I mentioned,
doesn&#8217;t actually work. </p>
<p> When I first looked at setting this messaging up and then
monitoring it, I searched for &#8220;nagios monitoring MQ webshere&#8221; and found
several pre-written plugins. I took each plugin and tested it for
usability and for accurate results and for meeting what we needed for
monitoring. </p>
<p>The message age plugin, in testing, actually returned a hard-coded
result rather than actually testing and returning a valid answer. I
started to fix it, set it aside and haven&#8217;t resolved it. I don&#8217;t recall
the source for the plugin. Check each piece of code you download from
the internet - it may have gone through extensive development and
testing, or it could just as easily have been hacked together in an
hour. Your mileage may seriously vary and I would highly recommend you
verify any of this before you bet your job on it. </p>
<p>Here&#8217;s the qdepth plugin - I think I wrote or re-wrote this pretty
much from scratch, but the original concept for parsing runmcsc came
from one of the plugins I downloaded, written by Kyle O&#8217;Donnell - the
channel plugin has his original author credit intact. This plugin has
alerted once to an increasing qdepth, which turned out to be an issue
with an SSL certificate. </p>
<hr />
<code><br />
#! /bin/perl</code>
<p><code>## wmq_check_qdepth.pl<br />
#<br />
# nrpe (nagios) script to check websphere qdepth</code></p>
<p><code># uses runmqsc binary<br />
#<br />
# display queue ('APP.REQUEST')<br />
#      8 : display queue ('APP.REQUEST')<br />
#      AMQ8409: Display Queue details.<br />
#      QUEUE(APP.REQUEST)                 TYPE(QLOCAL)<br />
#      ACCTQ(QMGR)                             ALTDATE(2008-01-22)<br />
#      ALTTIME(14.18.23)                       BOQNAME( )<br />
#      BOTHRESH(0)                             CLUSNL( )<br />
#      CLUSTER( )                              CLWLPRTY(0)<br />
#      CLWLRANK(0)                             CLWLUSEQ(QMGR)<br />
#      CRDATE(2008-01-22)                      CRTIME(14.18.23)<br />
#      CURDEPTH(0)                             DEFBIND(OPEN)<br />
#      DEFPRTY(0)                              DEFPSIST(NO)<br />
#      DEFSOPT(SHARED)                         DEFTYPE(PREDEFINED)<br />
#      DESCR( )                                DISTL(NO)<br />
#      GET(ENABLED)                            HARDENBO<br />
#      INITQ( )                                IPPROCS(0)<br />
#      MAXDEPTH(5000)                          MAXMSGL(4194304)<br />
#      MONQ(QMGR)                              MSGDLVSQ(PRIORITY)<br />
#      NOTRIGGER                               NPMCLASS(NORMAL)<br />
#      OPPROCS(0)                              PROCESS( )<br />
#      PUT(ENABLED)                            QDEPTHHI(80)<br />
#      QDEPTHLO(20)                            QDPHIEV(DISABLED)<br />
#      QDPLOEV(DISABLED)                       QDPMAXEV(ENABLED)<br />
#      QSVCIEV(NONE)                           QSVCINT(999999999)<br />
#      RETINTVL(999999999)                     SCOPE(QMGR)<br />
#      SHARE                                   STATQ(QMGR)<br />
#      TRIGDATA( )                             TRIGDPTH(1)<br />
#      TRIGMPRI(0)                             TRIGTYPE(FIRST)<br />
#      USAGE(NORMAL)</code></p>
<p><code>###  Variables  ###</code></p>
<p><code># test values set if this flag is true (1)<br />
### THIS MUST BE SET TO 0 IN PRODUCTION!!! ###<br />
my $test = 0;</code></p>
<p><code># debug flag (adds messages)<br />
my $debug = 0;<br />
my $LOG = "/tmp/wmq_check_qdepth.pl.log";</code></p>
<p><code># runmqsc binary<br />
my $MQSC = "/opt/mqm/bin/runmqsc";</code></p>
<p><code>###    ARGS    ###</code></p>
<p><code># first argument is warn level<br />
my $WARN = shift;<br />
# second arg is crtitical level<br />
my $CRIT = shift;</code></p>
<p># third arg is queue name<br />
my $QUEUE = shift;</p>
<p><code># set for dev purposes<br />
if ($test) {<br />
$WARN = 5;<br />
$CRIT = 10;<br />
$QUEUE = "1A33.EVG.REQUEST";<br />
}</code></p>
<p><code># validate<br />
# WARN and CRIT must be greater than 0 and CRIT must be greater than WARN<br />
unless (($WARN &gt; 0) &amp;&amp; ($CRIT &gt; 0)) {<br />
print ("Command Failed:  WARN and CRIT levels must be greater than 0"n");<br />
exit 3;<br />
}<br />
unless ($CRIT &gt; $WARN) {<br />
print ("Command Failed:  CRIT must be greater than WARN"n");<br />
exit 4;<br />
}</code></p>
<p><code>###    Subs    ###</code></p>
<p><code>###    MAIN    ###</code></p>
<p><code># run query<br />
my $result = `echo "display queue ('${QUEUE}')" | $MQSC | grep CURDEPTH`;<br />
print ("result: $result"n") if $debug;<br />
# parse result<br />
my @lines = split (""n", $result);  # divide into an array by end of line...<br />
# each element of the array will contain a single line<br />
# set variables<br />
my ($PARAM, $VALUE);</code></p>
<p><code>for my $line (@lines) {<br />
# each line is one or two elements like "QDPLOEV(DISABLED)                       QDPMAXEV(ENABLED)"<br />
# divide those...<br />
my ($first, $discard) = split (' ', $line);<br />
print (""$first: $first   "$discard $discard"n") if $debug;<br />
($PARAM, $VALUE) = split ('"(', $first);<br />
$VALUE =~ s/")//;<br />
print (""$PARAM: $PARAM    "$VALUE: $VALUE"n") if $debug;<br />
}</code></p>
<p><code># testing value<br />
$VALUE = 13 if $test;<br />
# check for $WARN and $CRIT levels, exit 0 as OK, 1 as warn or 2 as critical<br />
if ($VALUE == 0) {<br />
print ("OK:  found qdepth for $QUEUE at 0"n");<br />
exit 0;<br />
} elsif ($VALUE &lt; $WARN) {<br />
print ("OK:   found qdepth for $QUEUE at $VALUE"n");<br />
exit 0;<br />
} elsif (($VALUE &gt;= $WARN) &amp;&amp; ($VALUE &lt; $CRIT)) {<br />
print ("WARN: qdepth of $QUEUE is at $VALUE:  exceeds WARN thresh of $WARN"n");<br />
exit 1;<br />
} elsif ($VALUE &gt;= $CRIT) {<br />
print (&#8221;CRITICAL:  qdepth for $QUEUE at $VALUE: exceeds CRITICAL thresh of $CRIT"n&#8221;);<br />
exit 2;<br />
}<br />
</code></p>
<hr />
<p>This is the channel status plugin - I may have re-written the
original data gathering runmssc string, but the majority of the plugin
remained intact&#8230;</p>
<hr />
<code><br />
#!/bin/ksh<br />
#<br />
# check queue manager status<br />
#<br />
# Kyle O'Donnell <kyle[dot]odonnell[at]gmail[dot]com><br />
#<br />
#$Id: check_mq_channel,v 1.2 2007/04/04 14:36:02 kodonnel Exp $<br />
#<br />
# debug<br />
DATE=`date`<br />
LOG=&#8221;/tmp/nrpe_check_mq_channel.sh.log&#8221;<br />
echo &#8220;&#8221; &gt;&gt; $LOG<br />
echo $DATE &gt;&gt; $LOG<br />
echo &#8220;&#8221; &gt;&gt; $LOG<br />
[ $# -ne 2 ] &amp;&amp; echo &#8220;usage: $0 <channel> <queue manager="">&#8221; &amp;&amp;  exit 3<br />
channel=$1<br />
qmgr=$2<br />
echo &#8220;channel: $channel  qmanager: $qmgr&#8221; &gt;&gt; $LOG<br />
RUNMQSC=&#8221;/opt/mqm/bin/runmqsc&#8221;<br />
chanstatus=`echo &#8220;dis chs(${channel}) status&#8221; | ${RUNMQSC} ${qmgr} | grep -i &#8220;status(running)&#8221;`<br />
echo &#8220;channel status result:  $chanstatus&#8221; &gt;&gt; $LOG<br />
if echo $chanstatus |grep -i &#8220;status(running)&#8221; &gt; /dev/null 2&gt;&amp;1; then<br />
STATE=0<br />
printf &#8220;${channel} on ${qmgr} running&#8221;<br />
echo &#8220;&#8221;<br />
echo &#8220;&#8221;<br />
else<br />
STATE=2<br />
printf &#8220;${channel} on ${qmgr} not running&#8221;<br />
echo &#8220;&#8221;<br />
echo &#8220;&#8221;<br />
fi<br />
echo &#8220;state:  $STATE&#8221; &gt;&gt; $LOG<br />
exit $STATE;<br />
</queue></channel></kyle[dot]odonnell[at]gmail[dot]com></code>
<hr />
<p> Here&#8217;s the server.cfg file for the Websphere MQ machine on the nagios server:</p>
<hr />
<p><code><br />
define service {<br />
use                             generic-service<br />
host_name                       mq1<br />
service_description             Host Alive<br />
check_period                    24x7<br />
contact_groups                  unix-administrators<br />
notification_period             24x7<br />
check_command                   check-host-alive<br />
}</code></p>
<p><code>define service {<br />
use                             generic-service<br />
host_name                       mq1<br />
service_description             Sonic Bridge java process<br />
check_period                    24x7<br />
contact_groups                  esb-administrators<br />
notification_period             24x7<br />
check_command                   check_unix_proc!mqm!1!java<br />
}</code></p>
<p><code>define service {<br />
use                             generic-service<br />
host_name                      mq1<br />
service_description             SSB queue depth EVGPQM01.DEAD.QUEUE message age<br />
check_period                    24x7<br />
contact_groups                  systems-services,help_desk<br />
notification_period             24x7<br />
check_command                   wmq_check_qdepth!1!3!QMGR01!QMGR01.DEAD.QUEUE<br />
}</code></p>
<p><code>define service {<br />
use                             generic-service<br />
host_name                       mq1<br />
service_description             server queue depth APPLICATION.RESPONSE<br />
check_period                    24x7<br />
contact_groups                  systems-services,help_desk<br />
notification_period             24x7<br />
check_command                   wmq_check_qdepth!5!10!APPLICATION.RESPONSE<br />
}</code></p>
<p><code>define service {<br />
use                             generic-service<br />
host_name                       mq1<br />
service_description             server queue depth OPPOSITE-QMGR<br />
check_period                    24x7<br />
contact_groups                  systems-services,help_desk<br />
notification_period             24x7<br />
check_command                   wmq_check_qdepth!5!10!OPPOSITE-QMGR<br />
}</code></p>
<p><code>define service {<br />
use                             generic-service<br />
host_name                       mq1<br />
service_description             WMQ command server<br />
check_period                    24x7<br />
contact_groups                  systems-services,help_desk<br />
notification_period             24x7<br />
check_command                   check_unix_proc!mqm!1!amqpcsea<br />
}</code></p>
<p><code>define service {<br />
use                             generic-service<br />
host_name                       mq1<br />
service_description             WMQ Critical process manager<br />
check_period                    24x7<br />
contact_groups                  systems-services,help_desk<br />
notification_period             24x7<br />
check_command                   check_unix_proc!mqm!1!amqzmuc0<br />
}</code></p>
<hr />
<p>The strategy is to monitor qdepth and processes specific to IBM
WebSphere MQ on the Websphere MQ server, along with the normal UNIX
processes and disk space. </p>
<p>— dsm</p>
<div>
<span>
<strong>Share and Enjoy:</strong>
These icons link to social bookmarking sites where readers can share and discover new web pages.</span></div>
<br />
<br />
<br />
<h3 id="comments">One Response to &#8220;how to monitor ibm mq from nagios&#8221;</h3>
<ol>
    <div id="spacer">
    <li id="comment-65">Nice article!  I hadn&#8217;t been paying attention and didn&#8217;t know there were modules for Nagios to check WMQ.
    <p>How about this for checking queue depth&#8230;</p>
    <p><code><br />
    # Isolate the CURDEPTH element to a line, then strip the attribute so Perl gets only the value<br />
    my $curdepth = `echo "display queue ('${QUEUE}')" | $MQSC $QMGRNAME |
    tr ')' '"n' | tr ' ' '"n' | grep CURDEPTH | tr '(' '"n' | grep -v
    CURDEPTH`;<br />
    </code></p>
    <p><code><br />
    if ($curdepth == '0') {<br />
    # Look for literal '0'<br />
    } elsif ($curdepth &gt; 0) {<br />
    # Check against $WARN and $CRIT<br />
    } else {<br />
    # runmqsc command failed.  QMgr down?<br />
    }<br />
    </code></p>
    <p>Note that I added the QMgr name to the runmqsc command to handle
    cases where the QMgr is not set as the default or there is more than
    one. I also added logic to catch the case where WMQ is down.</p>
    <p>In the case of process monitoring, amqzmuc0 is the log formatter and
    I don&#8217;t think it runs in all cases. A better choice might be amqzxma0
    which is the execution controller.</p>
    <p>&#8211; T.Rob</p>
    </li>
    </div>
</ol>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/269254.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-05-06 15:51 <a href="http://www.blogjava.net/ruoyoux/articles/269254.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用nagios来监控网络服务器和网络服务</title><link>http://www.blogjava.net/ruoyoux/articles/269249.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 06 May 2009 07:36:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/269249.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/269249.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/269249.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/269249.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/269249.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 用nagios来监控网络服务器和网络服务nagios可以对服务器进行全面的监控，包括服务（apache、mysql、ntp、dns、disk、qmail和sshd等等）的状态，服务器的状态（up、down等等）。它是一个完全GPL协议的开源软件包，包含有nagios主程序和它的各个插件，配置非常灵活，可以监视的项目很多，可以自定义shell脚本进行监控服务，非常适合大型网络。g9...&nbsp;&nbsp;<a href='http://www.blogjava.net/ruoyoux/articles/269249.html'>阅读全文</a><img src ="http://www.blogjava.net/ruoyoux/aggbug/269249.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-05-06 15:36 <a href="http://www.blogjava.net/ruoyoux/articles/269249.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux下开机自动启动Oracle脚本</title><link>http://www.blogjava.net/ruoyoux/articles/267412.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Fri, 24 Apr 2009 09:51:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/267412.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/267412.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/267412.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/267412.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/267412.html</trackback:ping><description><![CDATA[<h3 entry-title="">
<a href="http://langalang.blogspot.com/2008/10/linuxoracle.html">linux下开机自动启动Oracle脚本</a>
</h3>
<div>最近自己的NC项目跑在Linux环境下。把安装过程慢慢的写下来。</div>
<div><br />
</div>
<div>===========<span style="border-collapse: collapse; white-space: pre;">linux下<span style="border-collapse: separate; white-space: normal;">开机自动启动Oracle脚本============</span></span></div>
<div>#<strong>注意：例子中的oralce命令在/home/oracle/oracle/product/10.2.0/db_1/bin目录。</strong></div>
<div>#你可以自己修改成自己的目录。</div>
<div><br />
</div>
<blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #!/bin/bash</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #alang 2008-10-19</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #root</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #chkconfig: 345 51 49</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #description: starts the oracle dabase deamons</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #ORA_HOME=/home/oracle/oracle/product/10.2.0/db_1</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #ORA_OWNER=oracle</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> case "$1" in</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> 'start')</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo -n "Starting oracle10g ... "</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> su - oracle -c "/home/oracle/oracle/product/10.2.0/db_1/bin/dbstart"</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo "Done."</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo "Starting Oracle Listeners ... " </blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> su - oracle -c "/home/oracle/oracle/product/10.2.0/db_1/bin/lsnrctl start"</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo "Done."</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #启动web管理界面:<a href="http://host_ip_address:1158/em">http://host_ip_address:1158/em</a></blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #su - oracle -c "/home/oracle/oracle/product/10.2.0/db_1/bin/emctl start dbconsole"</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> touch /var/lock/subsys/oracle10g</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo ""</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> ;;</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> 'stop')</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo -n "shutting down oracle10g ...  "</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> su - oracle -c "/home/oracle/oracle/product/10.2.0/db_1/bin/dbshut" </blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo -n "dbshut ok !"</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> su - oracle -c "/home/oracle/oracle/product/10.2.0/db_1/bin/lsnrctl stop"</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo -n "lsnrctl stop ok !"</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> #su - oracle -c "/home/oracle/oracle/product/10.2.0/db_1/bin/emctl stop dbconsole"</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> su - root -c "/home/oracle/ufsoft/stop.sh"</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> rm -f /var/lock/subsys/oracle10g</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> ;;</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> 'restart')</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo -n "restarting oracle10g ... "</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> $0 stop</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> $0 start</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> ;;</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> *)</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> echo "Usage: oracle {start|stop|restart} "</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> exit 1</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"><br />
</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> esac</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> exit 0</blockquote>
<div><br />
</div>
<div><br />
</div>
<div>============建立一个名为oralce10g的脚本==========</div>
<blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> [root@cwserver ~]# gedit /etc/rc.d/init.d/oracle10g</blockquote>
<div>#复制粘贴本文开头的脚本。或者直接使用附件中的oracle10g文件</div>
<div>#给予执行权限</div>
<blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> [root@cwserver ~]# chmod 755 /etc/rc.d/init.d/oracle10g</blockquote>
<div>#注意：例子中的oralce命令在/home/oracle/oracle/product/10.2.0/db_1/bin目录。</div>
<div>你可以自己修改成自己的目录。</div>
<div><br />
</div>
<div>============添加到启动、关闭、重启动服务序列中===</div>
<blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> $ ln -s /etc/rc.d/init.d/oracle10g /etc/rc.d/rc2.d/S99oracle10g</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> $ ln -s /etc/rc.d/init.d/oracle10g /etc/rc.d/rc3.d/S99oracle10g</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> $ ln -s /etc/rc.d/init.d/oracle10g /etc/rc.d/rc5.d/S99oracle10g</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> $ ln -s /etc/rc.d/init.d/oracle10g /etc/rc.d/rc0.d/K01oracle10g </blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> $ ln -s /etc/rc.d/init.d/oracle10g /etc/rc.d/rc6.d/K01oracle10g</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"><br />
</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;">============添加并启动察看服务=============================</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;">$/sbin/chkconfig --add /etc/rc.d/init.d/oracle10g</blockquote><blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;">$/sbin/chkconfig --list /etc/rc.d/init.d/oracle10g</blockquote></blockquote>
<div><br />
</div>
<div>============修改Oracle系统配置文件/etc/oratab=====</div>
<blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> $ gedit /etc/oratab</blockquote>
<div>最后一行更改为：</div>
<blockquote style="border-left: 1px solid #cccccc; margin: 0px 0px 0px 0.8ex; padding-left: 1ex;"> orcl:/home/oracle/oracle/product/10.2.0/db_1:Y</blockquote>
<div><br />
</div>
<div>============end==大功告成====================</div>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/267412.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-04-24 17:51 <a href="http://www.blogjava.net/ruoyoux/articles/267412.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Preventing access to .svn folders  or a file   in Apache</title><link>http://www.blogjava.net/ruoyoux/articles/266558.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Mon, 20 Apr 2009 07:07:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/266558.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/266558.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/266558.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/266558.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/266558.html</trackback:ping><description><![CDATA[&lt;Location /obcart/index.php&gt;<br />
&nbsp;Order Deny,Allow<br />
&nbsp;Deny from All<br />
&nbsp;Satisfy All<br />
&lt;/Location&gt;<br />
<br />
RedirectMatch 404 /".svn(/|$)<br />
<br />
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------<br />
This is straight from the mailing list with grateful thanks to Ryan Schmidt.
<p>Sometimes I can be a bit slow so I hadn't even considered blocking access to the <code>.svn</code> folders on this and other sites I maintain.  I have now!  There are two solutions:</p>
<pre>&lt;Files ".svn"&gt;<br />
<br />
Order allow,deny<br />
<br />
Deny from all<br />
<br />
&lt;/Files&gt;<br />
<br />
&lt;DirectoryMatch "/".svn/"&gt;<br />
<br />
Order allow,deny<br />
<br />
Deny from all<br />
<br />
&lt;/DirectoryMatch&gt;<br />
<br />
</pre>
<p>
and:</p>
<pre>RedirectMatch 404 /".svn(/|$)</pre>
<br />
====================================================================================================<br />
<br />
<br />
<h1><a href="http://www.ducea.com/2006/08/11/apache-tips-tricks-deny-access-to-some-folders/" rel="bookmark" title="Permanent Link to Apache Tips &amp; Tricks: Deny access to some folders">Apache Tips &amp; Tricks: Deny access to some folders</a></h1>
<p><strong>Applies</strong>: apache 1.3.x / apache 2.0.x<br />
Required apache module: <strong>mod_access</strong><br />
<strong>Scope</strong>: global server configuration, virtual host, directory, .htaccess<br />
<strong>Type</strong>: security</p>
<p><strong>Description</strong>: How to deny access to certain folders and the files inside them.<br />
<strong>Useful</strong>: to deny access to certain folders containing
private information (log files, source code, password files, etc.). The
example shown here will address the <a href="http://www.ducea.com/2006/07/21/apache-tips-tricks-deny-access-to-certain-file-types/#comments">question posted by Saul Howard</a> on how to deny access to all the <strong>subversion directories</strong> (.svn).</p>
<p>I a previous tip (<a href="http://www.ducea.com/2006/07/21/apache-tips-tricks-deny-access-to-certain-file-types/">Deny access to certain file types</a>) I have showed how we can <strong>deny access to files</strong>
using a particular filename or all the files with a particular
extension or any regexp we can match the files. In this post we will <strong>block access to folders</strong>, so instead of using the  &lt;Files&gt; directive we will be using the  <strong>&lt;Directory&gt;</strong> section.</p>
<h3>Allow/Deny Directive in &lt;Directory&gt;</h3>
<p>Let&#8217;s see how we can deny access to all the <strong>.svn</strong> folders that exist on the server.<br />
In order to achieve this we will add the following configuration lines
in the appropriate context (either global config, or vhost/directory,
or from .htaccess):</p>
<p><code>&lt;Directory  ~ "".svn"&gt;<br />
Order allow,deny<br />
Deny from all<br />
&lt;/Directory&gt;</code><br />
Similar to this we can deny access to other folders we might need&#226;€&#166;</p>
<p>Note: this will show a <em>Forbidden page</em> (code <strong>403</strong>) even if the folder does not exist and it is just called from the browser in the url.<br />
Another way how this can be quickly accomplished is by using a <strong>Rewrite rule</strong>:</p>
<pre><code>RewriteRule ^(.*/)?"".svn/ - [F,L]</code></pre>
<p>or using a <strong>redirect</strong>:</p>
<pre><code>RedirectMatch 404 /"".svn(/|$)</code></pre>
<p>(in this last example I am using <strong>404</strong> as the
returned code so this looks like the folder doesn&#8217;t exist on the
server; of course if you prefer you can return 403 - forbidden code).</p>
<p>Go to:<br />
<a href="http://www.ducea.com/2006/06/08/apache-tips-tricks/">Main page of all my Apache Tips &amp; Tricks</a></p>
<br />
<br />
<br />
<img src ="http://www.blogjava.net/ruoyoux/aggbug/266558.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-04-20 15:07 <a href="http://www.blogjava.net/ruoyoux/articles/266558.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Pair programming and agile </title><link>http://www.blogjava.net/ruoyoux/articles/266181.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Fri, 17 Apr 2009 08:45:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/266181.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/266181.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/266181.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/266181.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/266181.html</trackback:ping><description><![CDATA[Let's change the email subject so Tim can stop scramming on us. :)<br />
<br />
Interesting point that Bill pointed out is the availability of the resource. I would like to have a discussion on it. As the whole idea of pair programming is to raise the overall team productivity , so the correct statement should be as follow:<br />
<br />
"Solo programming is bad so i don't want too. And we also need to think about the availability of the resource as the productivity of solo programming is really low."<br />
<br />
<br />
The reason that people always think pair programming is a waste, because:<br />
You are putting two developer to do a task that can be done by one developer.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1. However, this is totally an illustration , you will realize the truth situation when you dig deeper:<br />
Solo , there are often situation that you are fooled by a simple typo , and spending few days to find it. You may finally solve it yourself, or your bored colleagues come to have a chat with you, look at your screen, and scrum out "You got a typo"...........&nbsp;&nbsp; The later case is an example of power in pair programming ,i.e., navigating and discover what you overlooked.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1. Solo, you may fall in sleep, low/no productivity.&nbsp; Pair , your partner will not let's you.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2. Solo, you play with msn and email . Pair, two developers won't get the chance.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 3. Solo, it's easily that you are moved from development to research, not doing the real thing. Pair, someone will warn you and drag you back.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 4. Solo, you can't think of a solution, not coz you are not good, but you are just not there. Pair, two brains always have a more complete solution.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 5. Solo, you learn something new yourself, wasting 4 days to pick up someone can teach you in an hour. Pair, both got trained and improved all the time.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 6. Of course, it's also correct that we should not drag everyone to pair programming at start for various reason, starting with a small groups of&nbsp; interested developers is much better.<br />
<br />
<br />
F.Y.I. , I got 11 developers signed up about tonight event. <br />
<br />
And please click a confirm on facebook if you can.<br />
http://www.facebook.com/event.php?eid=8836123613Let's change the email subject so Tim can stop scramming on us. :)<br />
<br />
Interesting point that Bill pointed out is the availability of the resource. I would like to have a discussion on it. As the whole idea of pair programming is to raise the overall team productivity , so the correct statement should be as follow:<br />
<br />
"Solo programming is bad so i don't want too. And we also need to think about the availability of the resource as the productivity of solo programming is really low."<br />
<br />
<br />
The reason that people always think pair programming is a waste, because:<br />
You are putting two developer to do a task that can be done by one developer.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1. However, this is totally an illustration , you will realize the truth situation when you dig deeper:<br />
Solo , there are often situation that you are fooled by a simple typo , and spending few days to find it. You may finally solve it yourself, or your bored colleagues come to have a chat with you, look at your screen, and scrum out "You got a typo"...........&nbsp;&nbsp; The later case is an example of power in pair programming ,i.e., navigating and discover what you overlooked.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1. Solo, you may fall in sleep, low/no productivity.&nbsp; Pair , your partner will not let's you.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2. Solo, you play with msn and email . Pair, two developers won't get the chance.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 3. Solo, it's easily that you are moved from development to research, not doing the real thing. Pair, someone will warn you and drag you back.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 4. Solo, you can't think of a solution, not coz you are not good, but you are just not there. Pair, two brains always have a more complete solution.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 5. Solo, you learn something new yourself, wasting 4 days to pick up someone can teach you in an hour. Pair, both got trained and improved all the time.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 6. Of course, it's also correct that we should not drag everyone to pair programming at start for various reason, starting with a small groups of&nbsp; interested developers is much better.<br />
<br />
<br />
F.Y.I. , I got 11 developers signed up about tonight event. <br />
<br />
And please click a confirm on facebook if you can.<br />
http://www.facebook.com/event.php?eid=8836123613
<img src ="http://www.blogjava.net/ruoyoux/aggbug/266181.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-04-17 16:45 <a href="http://www.blogjava.net/ruoyoux/articles/266181.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>User Story Estimation Techniques</title><link>http://www.blogjava.net/ruoyoux/articles/266180.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Fri, 17 Apr 2009 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/266180.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/266180.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/266180.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/266180.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/266180.html</trackback:ping><description><![CDATA[One of the great things about working as a consultant is the ability to try out many different ideas and adapting your personal favorite process to include things that work. This article gives the details about user story estimation techniques that I've found effective. <br />
<br />
<br />
<br />
Powers of two <br />
Originally I estimated stories as one, two, three, four or as small, medium, large, extra-large. It was always meant to be understood that a medium was twice the size of a small and a large was twice the size of a medium (and so on), but that never seemed to translate well when it came to planning. Then someone recommended to me that I try powers of two. Suddenly we were speaking a language that the business could understand. They knew that an 8 was significantly bigger than a 1. I believe the sizes one, two, four, eight are also much more appropriate. As stories get larger they almost always contain more unknown and risk. A powers of two scale emphasizes the risk associated with large stories.<br />
<br />
<br />
Use four values <br />
I was once on a project that started with 1, 2, 4, 8 as their estimation values. After the first two estimation sessions less than 5% of the stories were ones and about 30% of the stories were twos. The project manager decided to get rid of the one value because it made his life easier. An interesting thing happened at each subsequent estimation meeting, suddenly only 5% of the stories were twos and many more stories had become fours. I don't think that the developers consciously changed their scale, but developers are conditioned to be skeptical. Few developers are willing to say with certainty that any given story will be as easy as the scale allows. After witnessing this type of behavior on a few different projects, I prefer a minimum of four point values. I also prefer a maximum of 4 point values. After all, it's nothing more than an estimate. If you try to give too much precision to an estimate you'll end up having to account for why you missed the mark. The idea is to get a rough idea, not a rigid plan to live off of.<br />
<br />
<br />
No averages or numbers not on the scale <br />
Four values allow you to get a rough estimate without spending unnecessary time focusing on precision. Sometimes a story feels larger than a two but smaller than a four. The story should not be estimated as a three. There's really no reason to use a three. The story carries enough risk or unknowns that it is not a two; therefore, it's very likely that it will actually be a four. Using an average or an off scale number can briefly (and unnecessarily) confuse a team member or stakeholder. Also, in the big picture of the project, the occasional uncommon estimate isn't likely to make much of a difference. Keep it simple, stick to the scale.<br />
<br />
<br />
Vote independently <br />
It's human nature to be influenced by other people. If a technical leader says a story is a two, it's likely that the rest of the team will follow his lead. For this reason I prefer an estimation process that lets each team member vote independently. This can be done by using sheets of paper that no one reveals until everyone is ready. Another option (that I prefer) is to give your estimation rock-paper-scissors (RPS) style. In our estimation meetings we talk about a story until we are ready to estimate then we all "throw" our estimations the same as you would "throw" rock, paper, or scissors. What I mean by "throw our estimation" is that if we think it's a 1 we point 1 finger. Likewise a 2 is two fingers and 4 is four fingers. If you need to throw an 8, you can use both hands.<br />
<br />
<br />
Take the largest estimate <br />
Even when reminded, developers seem to have a hard time estimating with a team in mind. If a developer thinks they can do the story in 1 day, they throw 1 finger. Unfortunately, that developer may not be available to do the story, and then some other team member is stuck working on a story that they thought was a 2 or even a 4. I prefer to always take the largest estimate thrown by any team member. You may consider this to be sandbagging, but in reality it's likely that each team member has identified different risks and the team member with the largest estimate has probably correctly identified that there is more risk than the other members have thought of.<br />
<br />
Taking the largest estimate has additional benefits. If you must agree on a lower estimate then the team member with the larger estimate will need to discuss why they chose a larger value. This discussion can be uncomfortable for developers who are less senior on the team. They may not know how to do something as quickly, based on limited experience with the language or tools. Their concerns are often justified by their skill level, and it would be unfortunate if they felt uncomfortable giving their true estimate because they were afraid to discuss why it was higher.<br />
<br />
Any discussion around taking a higher or lower value may lead to the entire team raising their value, or it may lead to that developer uncomfortably lowering their estimate. Either way, you'll need to spend more time talking and you wont have gained--in the end it's consistency that matters. You always know how many stories you expect to get done in an iteration by tracking velocity*. Therefore, even if your estimates are "bloated" so will your velocity be, thus it has no effect on planning.<br />
<br />
Finally, taking the largest estimate can help save time in an estimation meeting. If any member of the team believes the story is an 8 he can speak up at any time while discussing the story and announce that he is going to throw an eight. Unless someone else believes that there is a large estimation gap among team members, there's no reason to continue talking about the story since it will ultimately become an eight anyway.<br />
<br />
<br />
Large estimate gaps <br />
When estimating it's usually the exception that the entire team agrees on the size of a story. Like I previously said, I like to handle the mismatch by always taking the larger estimate. However, sometimes a large gap represents a misunderstanding. For this reason any time there is a two value gap in estimation, additional conversation always occurs (e.g. if a team member throws a 1 and another throws a 4, some clarification needs to occur). Discussing large gaps also ensures that taking the largest estimate has less chance of being abused.<br />
<br />
<br />
Insufficient information <br />
On occasion a story may need leave the meeting unestimated. It's better to ask for more information than to give an estimate that you are uncomfortable with. An estimate of 8 implies that it's a large story, but you expect it to take twice as long as a 4. Therefore, don't simply estimate ill-defined stories as eights, because you will likely be expected to get it done in the same amount of time as it takes to get two stories estimated as fours completed. The goal of an estimation meeting isn't to estimate all the stories, it's to provide estimates on the stories that provide sufficient information.<br />
<br />
<br />
Required involvement <br />
No one enjoys estimation meetings (okay, no one I know). In my past projects the fastest reader would read the story aloud, the developers would ask the domain experts questions, and then they would estimate. When the developers weren't asking the domain experts questions, the domain experts usually did other things on their laptops. At first glance I thought this was a good use of their time, but things got missed. Later I joined a project where the manager insisted that we go around the room and make everyone read a story when it was their turn. Suddenly the domain experts were engaged because they were worried about looking silly when it was their turn to read. The meetings became much more valuable due to everyone's involvement.<br />
<br />
<br />
Pigs and Chickens <br />
In a ham-and-eggs restaurant, the pig is committed but the chicken is simply involved.<br />
<br />
I often hear that the business shouldn't influence developer estimates because developers are pigs and the business is full of chickens. I actually think this is a bad analogy. It's more likely that a bad product will get the business team fired than the technology team. I'm sure the business feels just as committed as the developers. However, it is a conflict of interest to let the business interfere with estimates.<br />
<br />
It's as simple as this, the business wants to know what functionality they can get in the next iteration. To know what to expect they need estimates. Since the business will not be writing the code, they cannot contribute proper estimates. The more they are involved (in the actual estimation), the less likely it is that they will receive realistic estimates. The best domain experts answer questions in meetings, but never assert in any way the level of effort it will take to complete any given story.<br />
<br />
<br />
Estimation group size <br />
Teams come in many different sizes. On smaller teams (6 or less) I suggest the entire team attend the estimation session. The many points of view are likely to solidify vision and positively contribute to an estimate. However, I believe there is a point of diminishing returns. Not everyone on a large team needs to be part of estimating each story. Additionally, it's an estimate, 6 people should be just as accurate as 15 people would be. If your team is larger than 6 people I suggest breaking into smaller groups for estimation. In general I like to get at least 3 people to estimate any given story, but no more than 6.<br />
<br />
<br />
New stories <br />
New stories come in two forms: new feature requests and stories that split. I generally wait to estimate new stories based on their priority. If a story needs to be done in the next iteration, it generally requires an immediate estimate. However, if the new stories aren't going to be played for several iterations it can make sense to hold off until you have enough stories to justify an estimation meeting. I find estimates from estimation meetings to be more reliable, since they come from an environment where everyone is focused solely on estimation. Stories resulting from a split provide an additional complication: they likely already have an estimate. I strongly suggest that the new stories be estimated without taking into consideration the previous estimate. If a story carried enough risk or uncertainty that it required splitting, it's not likely that the estimate is realistic--ignore the original estimate.<br />
<br />
<br />
No laptops <br />
At least no laptops for developers. Print the story list for everyone, or project the list on the screen, but don't ask the developers to read the story list from their laptops. Laptops almost always find ways to distract developers, thus taking away from the goal of the meeting: Getting valuable estimates.<br />
<br />
<br />
Required participation <br />
This suggestion is a very important one. In theory, no developer from outside the team should be attending an estimation session. That means that every developer that attends an estimation session will potentially be tasked with working on a story that's being estimated. If a developer is not comfortable estimating a story, then I'm not comfortable with them working on the story. Of course, there are exceptions. I generally give new team members one week to come up to speed before I ask that they participate in an estimation session. But, in general, a developer who refuses to participate in estimation should signal that there's a bigger issue that needs to be resolved.<br />
<br />
<br />
Stale estimations <br />
Teams change, projects change, and random events occur. Whatever the reason, estimations can get stale. Stale estimations don't help anyone. The development team feels pressure to deliver to stale estimates and the business expects stories to be completed according to projected velocity. It doesn't matter why estimates get stale, what matters is that the estimates are no longer realistic and the plan is no longer reliable. I've never been part of a project where the estimates didn't go stale within 12-24 weeks. It's better to admit that an estimation is stale than it is to plan with inaccurate information. For this reason, I suggest revisiting any estimation that was given more than 12 weeks ago. The estimation will hopefully still be good, but giving the developers an opportunity to speak up given new information is nothing but helpful to the business.<br />
<br />
<br />
Bribes<br />
This is the easiest suggestion of all: Bring high quality snacks to all estimation meetings. Sugar has been scientifically linked to happiness, and happiness leads to collaboration. It's the simplest and cheapest possible way to make an estimation meeting something to look forward to. Keep in mind though, high quality is the key. If you bring the same snacks that are already sitting in the team room, it's not very exciting. On my last project I went to the bakery and got fresh baked assorted cookies every time I remembered there was a meeting.<br />
<br />
<br />
Credit<br />
I'd like to give special thanks to Brent Cryder, Dennis Byrne, Fred George, Joe Zenevitch, Mike Ward, and Sean Doran for helping me solidify and evolve these ideas. Just like every other list of people, mine surely leaves out other contributors, please forgive me for leaving you off.<br />
<br />
<br />
About the author<br />
Jay Fields is a software developer and consultant at ThoughtWorks. He has a passion for discovering and maturing innovative solutions. His most recent work has been in the Domain Specific Language space where he has delivered applications that empowered domain experts to author domain logic. He is also very interested in maturing software design through developer testing and software testing in general.<br />
<br />
<br />
<br />
*Velocity: The number of points you've completed over the life of the project divided by the number of iterations. E.g. If you've completed 20 points over 5 iterations, your velocity is 4. With a velocity of 4 you can expect to get as many stories done in an iteration where their estimates total 4 (e.g. 1 story estimated as a 4, 2 stories estimated as twos, 4 stories estimated as ones, etc)<br />
<br />
<br />
<br />
http://www.infoq.com/articles/agile-estimation-techniques<br />
<br />
<img src ="http://www.blogjava.net/ruoyoux/aggbug/266180.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-04-17 16:43 <a href="http://www.blogjava.net/ruoyoux/articles/266180.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Increase file descriptor limit under Linux to prevent java.net.SocketException: Too many open files
Increase file descriptor limit under Linux to prevent java.net.SocketException: Too many open files
Increase file descriptor limit under Linux to prev</title><link>http://www.blogjava.net/ruoyoux/articles/265441.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Tue, 14 Apr 2009 02:53:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/265441.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/265441.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/265441.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/265441.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/265441.html</trackback:ping><description><![CDATA[<h1>Increase file descriptor limit under Linux to prevent <br />
</h1>
<h1>java.net.SocketException: Too many open files</h1>
<h4>Get current limit:</h4>
<p><code>ulimit -n</code></p>
<p><code>cat /proc/sys/fs/file-nr</code></p>
<p>The default limit is 1024.</p>
<h4>Get current number of open file descriptors:</h4>
<p><code>lsof [-p pid] | wc -l</code></p>
<h4>Increase the limit:</h4>
<p>Edit <code>/etc/security/limits.conf</code>:</p>
<p><code>username hard nofile 32768</code></p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/265441.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-04-14 10:53 <a href="http://www.blogjava.net/ruoyoux/articles/265441.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>crontab </title><link>http://www.blogjava.net/ruoyoux/articles/258815.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Tue, 10 Mar 2009 07:42:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/258815.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/258815.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/258815.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/258815.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/258815.html</trackback:ping><description><![CDATA[<p>Once inside the editor, you will want to refer to the fields above
in order to schedule a cron job for the appropriate time. Here are some
examples:</p>
<p><strong class="spip">*/5 * * * * /home/adam/script.sh</strong> will execute <em>script.sh</em> every 5 minutes.  This will set crontab every 5 minutes.<br />
<strong class="spip">59 23 * * 1-5 /home/adam/script.sh</strong> will execute <em>script.sh </em>every day, monday through friday, at 11:59 p.m.<br />
<strong>0 0 * * 0 /home/adam/script.sh</strong> will execute <em>script.sh</em> once a week.  You could also specify <strong>@weekly </strong>instead of <em>0 0 * * 0</em>.</p>
<p><strong>0 23 1 * * /home/adam/script.sh</strong> will execute <em>script.sh </em>once a month, on the first, at 11:00 PM.  You could also specify <strong>@monthly </strong>in place of <em>0 23 1 * *</em>.</p>
<strong></strong>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/258815.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-03-10 15:42 <a href="http://www.blogjava.net/ruoyoux/articles/258815.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>svn中的branch和tag</title><link>http://www.blogjava.net/ruoyoux/articles/257553.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Tue, 03 Mar 2009 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/257553.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/257553.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/257553.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/257553.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/257553.html</trackback:ping><description><![CDATA[<div class="articleContent" id="articleBody">
<p>在SVN中Branch/tag在一个功能选项中，在使用中也往往产生混淆。<br />
<br />
在实现上，<font color="#0000ff">branch和tag，对于svn都是使用copy实现的</font>，所以他们在默认的权限上和一般的目录没有区别。至于何时用tag，何时用branch，完全由人主观的根据规范和需要来选择，而不是强制的（比如cvs）。<br />
<br />
一般情况下，<br />
tag，是用来做一个milestone的，不管是不是release，都是一个可用的版本。这里，应该是只读的。更多的是一个显示用的，给人一个可读（readable）的标记。<br />
branch，是用来做并行开发的，这里的并行是指和trunk进行比较。<br />
<br />
比
如，3.0开发完成，这个时候要做一个tag，tag_release_3_0，然后基于这个tag做release，比如安装程序等。trunk进入
3.1的开发，但是3.0发现了bug，那么就需要基于tag_release_3_0做一个branch，branch_bugfix_3_0，基于这
个branch进行bugfix，等到bugfix结束，做一个tag，tag_release_3_0_1，然后，根据需要决定
branch_bugfix_3_0是否并入trunk。<br />
<br />
对于svn还要注意的一点，就是它是<font color="#0000ff">全局版本号</font>，
其实这个就是一个tag的标记，所以我们经常可以看到，什么什么release，基于xxx项目的2xxxx版本。就是这个意思了。但是，它还明确的给出
一个tag的概念，就是因为这个更加的可读，毕竟记住tag_release_1_0要比记住一个很大的版本号容易的多。</p>
<p>&nbsp;<wbr></p>
<p>branches：分枝</p>
<p>当多个人合作，可能有这样的情况出现：John突然有个想法，跟原先的设计不太一致，可能是功能的添加或者日志格式的改进等等，总而言之，这个想法
可能需要花一段时间来完成，而这个过程中，John的一些操作可能会影响Sally的工作，John从现有的状态单独出一个project的话，又不能及
时得到Sally对已有代码做的修正，而且独立出来的话，John的尝试成功时，跟原来的合并也存在困难。这时最好的实践方法是使用branches。
John建立一个自己的branch，然后在里面实验，必要的时候从Sally的trunk里取得更新，或者将自己的阶段成果汇集到trunk中。</p>
<p>（svn copy SourceURL/trunk  DestinationURL/branchName  -m "Creating a private branch of xxxx/trunk." ）</p>
<p>trunk：主干</p>
<p>主干，一般来说就是开发的主要呆的地方，</p>
<p>tag:</p>
<p>在经过了一段时间的开发后，项目到达了一个里程碑阶段，你可能想记录这一阶段的代码的状态，那么你就需要给代码打上标签。</p>
<p>(svn cp <font color="#7b3a00">file:///svnroot/mojavescripts/trunk</font>  file:///svnroot/mojavescripts/tags/mirrorutils_rel_0_0_1 <br />
-m "taged mirrorutils_rel_0_0_1")</p>
<p>另有一说，无所谓谁对谁错。</p>
<p>trunk<span>：表示开发时版本存放的目录，即在开发阶段的代码都提交到该目录上。</span></p>
<p>branches<span>：表示发布的版本存放的目录，即项目上线时发布的稳定版本存放在该目录中。</span></p>
<p>tags<span>：表示标签存放的目录。</span></p>
<p><span>在这需要说明下分三个目录的原因，如果项目分为一期、二期、三期等，那么一期上线时的稳定版本就应该在一期完成时将代码</span>copy<span>到</span>branches<span>上，这样二期开发的代码就对一期的代码没有影响，如新增的模块就不会部署到生产环境上。而</span>branches<span>上的稳定的版本就是发布到生产环境上的代码，如果用户使用的过程中发现有</span>bug<span>，则只要在</span>branches<span>上修改该</span>bug<span>，修改完</span>bug<span>后再编译</span>branches<span>上最新的代码发布到生产环境即可。</span>tags<span>的作用是将在</span>branches<span>上修改的</span>bug<span>的代码合并到</span>trunk<span>上时创建个版本标识，以后</span>branches<span>上修改的</span>bug<span>代码再合并到</span>trunk<span>上时就从</span>tags<span>的</span>version<span>到</span>branches<span>最新的</span>version<span>合并到</span>trunk<span>，以保证前期修改的</span>bug<span>代码不会再合并。</span></p>
<p><span>轉自：</span></p>
<p><span><font color="#7b3a00">http://hi.baidu.com/stevenchan/blog/item/bb70c1951b576d4dd1135e3a<wbr>.html</font></span></p>
<p><span><font color="#7b3a00">http://hi.baidu.com/cc0cc/blog/item/f68cb0581e86add99d82043d<wbr>.html</font></span></p>
</div>
<br />
<img src ="http://www.blogjava.net/ruoyoux/aggbug/257553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-03-03 14:57 <a href="http://www.blogjava.net/ruoyoux/articles/257553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux 开机 自动 启动apache 脚本</title><link>http://www.blogjava.net/ruoyoux/articles/257368.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Mon, 02 Mar 2009 09:30:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/257368.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/257368.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/257368.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/257368.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/257368.html</trackback:ping><description><![CDATA[实例介绍：<br />
&nbsp;&nbsp; 1、在linux下安装了apache 服务（通过下载二进制文件经济编译安装、而非rpm包）、apache
服务启动命令：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /server/apache/bin/apachectl start&nbsp;&nbsp;&nbsp;
。让apache服务运行在运行级别3下面。&nbsp; 命令如下：<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 1）touch /etc/rc.d/init.d/apache<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vi /etc/rc.d/init.d/apache<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chown -R root /etc/rc.d/init.d/apache<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chmod 700 /etc/rc.d/init.d/apache<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ln -s /etc/rc.d/init.d/apache /etc/rc.d/rc3.d/S60apache&nbsp;&nbsp; #S
是start的简写、代表启动、K是kill的简写、代表关闭。60数字&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
代表启动的顺序。（对于iptv系统而言、许多服务都是建立在数据库启动的前提下才能够正常启动的、可以通过该数字就行调整脚本的&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
启动顺序））<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; apache的内容：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #!/bin/bash<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #Start httpd service<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /usr/local/site/apache/bin/apachectl start<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至此 apache服务就可以在运行级别3下 随机自动启动了。（可以结合chkconfig 对启动服务进行相应的调整）
<img src ="http://www.blogjava.net/ruoyoux/aggbug/257368.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-03-02 17:30 <a href="http://www.blogjava.net/ruoyoux/articles/257368.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>RRDTool</title><link>http://www.blogjava.net/ruoyoux/articles/257138.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 28 Feb 2009 05:12:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/257138.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/257138.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/257138.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/257138.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/257138.html</trackback:ping><description><![CDATA[<a href="http://im.nuk.edu.tw/~lee/rrdtool/#1">關於RRDtool</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/index.htm#2">安裝前準備工作</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#3">安裝RRDtool</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#4">開始使用RRDtool</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#5">建立RRD檔</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#6">抓取資料</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#7">更新RRD檔資料</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#8">繪製圖表</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#9">其他RRDtool的指令</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#10">簡單實作範例</a><br />
<a href="http://im.nuk.edu.tw/~lee/rrdtool/#11">RRDtool備份</a>
<hr />
<ul>
    <li><a name="1"></a><strong><font color="#ff0000">關於RRDtool</font></strong> </li>
</ul>
<p align="left">&nbsp;什麼是RRDtool?相信大部份的人都沒有聽過這個東東....不過，如果問起知不知道有MRTG這套程式，相信就有許多人聽過了。　打個比方來說明︰如果MRTG是一輛車子，那麼RRDtool就是製造車子的工廠了!&nbsp;&nbsp;&nbsp;&nbsp; 簡單講，RRDtool是一套可以把數據畫成圖表的程式，以時間為x軸、流量為y軸，而且可以動態更新圖表的程式，聽起來似乎非常的強大？沒錯，正是因為RRDtool的功能強大以致於它有不太容易學習的缺點，況且坊間有提到RRDtool的書籍可以說是少之又少(目前還沒看過)；網路上找？總共的中文教學文章只有酷學園Abelyang的那一篇。&nbsp;&nbsp;&nbsp;&nbsp; 反觀MRTG簡單又功能強大，學習文件頗多，能滿足大部份人的需求，但是如果您對於MRTG的統計方式不能認同，亦或是您有強烈customize統計圖表的需求，RRDtool將會是您最好的選擇！</p>
<p align="left"><img src="http://im.nuk.edu.tw/~lee/rrdtool/image/1.gif" border="0"  alt="" /><br />
(本圖取自RRDtool官方網站)</p>
<hr />
<ul>
    <li><a name="2"></a><font color="#ff0000"><strong>安裝前準備工作</strong></font> </li>
</ul>
<p align="left">&nbsp;本文以下的敘述皆實作於FreeBSD 6.0系統下，不過如果您的系統不是FreeBSD，不用擔心，大同小異啦 !&nbsp;&nbsp; 除了一些指令有小小的不同以外......&nbsp; 此外，因為RRDtool能做出來的只是圖表而已，一般來說，都是以放在WEB的方式讓管理者或是使用者能夠瀏覽，所以，請先安裝好WWW server&nbsp; (如:Apache)&nbsp; 。</p>
<hr />
<ul>
    <li><a name="3"></a><font color="#ff0000"><strong>安裝rrdtool</strong></font> </li>
</ul>
<p>在FreeBSD下︰</p>
<table height="28" width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000" height="24"><font color="#ffffff">LEE# cd /usr/ports/net/rrdtool/ </font><font color="#ffff00">//切換到ports中RRDtool的目錄</font><br />
            <font color="#ffffff">LEE# make install clean&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//安裝並清除安裝暫存的檔案</font><br />
            </td>
        </tr>
    </tbody>
</table>
<p>在Debian下:</p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">LEE# apt-get update&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//更新檔案清單</font><font color="#ffffff"><br />
            LEE# apt-get install rrdtool&nbsp; </font><font color="#ffff00">//使用apt安裝RRDtool套件</font></td>
        </tr>
    </tbody>
</table>
<p>其他linux則可以到<a href="http://www.rrdtool.org/">www.rrdtool.org</a>下載Source Code或是Binary檔安裝！</p>
<p>如果安裝過程沒有差錯，RRDtool就安裝完成了!&nbsp;&nbsp;&nbsp; 如何確定RRDtool能正常運作呢?&nbsp; 在console下輸入「rrdtool」，如果有看到以下畫面代表您的RRDtool已經可以正常運作囉！</p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">LEE# rrdtool<br />
            RRDtool 1.0.49 Copyright 1997-2004 by Tobias Oetiker &lt;tobi@oetiker.ch&gt;<br />
            <br />
            Usage: rrdtool [options] command command_options<br />
            <br />
            Valid commands: create, update, graph, dump, restore,<br />
            last, info, fetch, tune, resize, xport<br />
            <br />
            RRDtool is distributed under the Terms of the GNU General<br />
            Public License Version 2. (www.gnu.org/copyleft/gpl.html)<br />
            <br />
            For more information read the RRD manpages<br />
            <br />
            LEE#</font><br />
            </td>
        </tr>
    </tbody>
</table>
<p>如果沒有看到，請在確定您的安裝步驟有沒有錯誤！</p>
<hr />
<ul>
    <li><a name="4"></a><font color="#ff0000"><strong>開始使用RRDtool</strong></font> </li>
</ul>
<p>先說明一下RRDtool運作的大概流程︰</p>
<p><img src="http://im.nuk.edu.tw/~lee/rrdtool/image/pic.JPG" border="0"  alt="" />　　</p>
<p>步驟一︰建立RRD檔，這個檔說來說去就是RRDtool的「專屬」資料庫啦！RRDtool以自有的格式存放流量資料，下面會有比較詳細的說明。</p>
<p>步驟二︰「抓取資料」個人覺得是整個RRDtool最困難的一部分，因為RRDtool的資料是要靠自己弄出來，不若MRTG內建抓資料功能，但是卻因為如此，可以「餵」給RRDtool畫圖的資料彈性也比較大，例如︰snmp查詢結果、系統狀態、網頁中特定數字統計..等等。</p>
<p>步驟三︰抓下來的資料就用「rrdtool update」的指令更新步驟更新的RRD檔的內容，讓圖表能畫出最新的流量。</p>
<p>步驟四︰這就是重點啦！透過「rrdtool graph」的指令來依據RRD檔的資料繪圖，這也是使用者唯一看的到的東西，若規劃的不好會影響使用者閱讀上的困難！</p>
<p>迴圈︰由於要達成動態繪圖的圖表，第二步驟到第四步驟必須不斷的重複執行以維持資料的更新，目前知道要達成迴圈的方法有兩種︰1、在Script中使用迴圈；2、使用cron這個排班程式做排班。</p>
<p>以下將詳細的說明這四個步驟︰</p>
<hr />
<ul>
    <li><a name="5"></a><font color="#ff0000"><strong>建立RRD檔</strong></font>　 </li>
</ul>
<p>RRDtool 建檔語法<br />
<font color="#000000">rrdtool create filename<br />
[--start|-b start time]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#0000ff"> // "-s" 代表此RRD檔可以開始紀錄的時間，注意︰要把時間單位轉換成秒，1970/01/01算第一秒，用`date`指令可由系統幫您計算。</font><font color="#000000">&nbsp;<br />
[--step|-s step]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#0000ff">//意指每筆資料的間隔時間，一般使用者設定'300'，即每五分鐘為一間隔。</font><font color="#000000"><br />
[DS:ds-name:DST:heartbeat:min:max]<br />
[RRA:CF:xff:steps:rows]&nbsp;</font></p>
<p><font color="#000000">重要</font><font color="#000000">參數說明︰</font></p>
<p><font color="#0000ff">DS </font><font color="#000000">全名"Data Source"，就是資料來源。這有點像是在RRD檔這個資料庫建一個可以儲存資料的欄位。</font></p>
<p><font color="#000000">例︰DS:telnet:COUNTER:600:0:100000000</font></p>
<p><font color="#000000">DS表示式總共有六個欄位︰</font><font color="#336600">第一個欄位</font><font color="#000000">宣告這列式為DS表示式；</font><font color="#336600">第二個欄位</font><font color="#000000">宣告這個DS在RRD檔裡面的"欄位名稱"(Data Source Name)，此例宣告此欄叫做"telnet"(名稱可以自訂)；</font><font color="#336600">第三個欄位</font>叫做DST(Data Source Type)，習慣上常用 GAUGE(個別值,像CPU loading) 及COUNTER (累計值,像流量資料) 在產生圖檔時， GAUGE 是 100 就畫100在 Y 軸上；但如果是 COUNTER ，此次值為100，而前一值是 98，則會在Y軸上畫 2；<font color="#336600">第四個欄位</font>稱做有效期(heartbeat)，範例裡的值為'600'，假設要取12:00的資料，而前後300秒裡的值(11:55-12:05)經過平均或是取最大或最小都算是12:00的有效值；<font color="#336600">第五個欄位</font><font color="#000000">和</font><font color="#008000">第六個欄位</font><font color="#000000">為這個欄位允許可以存放的最大最小值，此例允許最小為0，最大為100000000，如果不想設限制可以再第五個欄位和第六個欄位以 "</font><font color="#0000ff">U:U</font><font color="#000000">"表示。</font></p>
<p><font color="#0000ff">RRA</font><font color="#000000">全名為Round Robin Archive，簡單來說就是其實就是什麼類資料要存幾筆，資料的儲存分成四類，分別為AVERAGE, MIN, MAX, LAST 意即平均值，最大值，最小值，最後一筆 。</font></p>
<p><font color="#000000">例︰0.5:1:603&nbsp;</font></p>
<p><font color="#000000">因為我們將 step 定為 300 秒是指若原計算時間點為 12:00 的話，記錄時要以 11:57:30~12:02:30 的平均值為主，這個值若在此時間點內只有一筆資料的話，其意即是平均值，所以此一值即表原 telnet&#8230;等共要記錄幾筆，603 是指要存 603 筆，若超過603筆，則最早之一筆將被移出。<br />
0.5:6:603 第三個欄位表示取 6 筆資料(每筆為 step 值，在此意即５分鐘)為平均值( 30 分鐘), 存 603 筆<br />
0.5:24:603 24 即二小時<br />
0.5:288:800 288 即一天&nbsp;</font></p>
<p><font color="#000000">以下為建檔的完整範例︰</font></p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">$LEE# rrdtool create lee.rrd -s 300 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//此列為建立'lee.rrd'這個資料檔，step值為300s</font><font color="#ffffff"><br />
            ?DS:input:COUNTER:600:0:100000000 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//Data Source第一欄</font><font color="#ffffff"><br />
            ?DS:output:COUNTER:600:0:100000000 \&nbsp;&nbsp;&nbsp;&nbsp; /</font><font color="#ffff00">/Data Source第-二欄</font><font color="#ffffff"><br />
            ?RRA:AVERAGE:0.5:1:603 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//每隔五分鐘(1*5)存一次資料的平均值</font><font color="#ffffff"><br />
            ?RRA:AVERAGE:0.5:6:603 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//每隔三十分鐘(6*5)存一次資料的平均值</font><font color="#ffffff"><br />
            ?RRA:AVERAGE:0.5:24:603 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//每隔兩小時(24*5)存一次資料的平均值</font><font color="#ffffff"><br />
            ?RRA:AVERAGE:0.5:288:603 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//每隔一天(288*5)存一次資料的平均值</font><font color="#ffffff"><br />
            ?RRA:MAX:0.5:1:603 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//每隔五分鐘存一次資料的最大值</font><font color="#ffffff"><br />
            ?RRA:MAX:0.5:6:603 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//每隔三十分鐘存一次資料的最大值</font><font color="#ffffff"><br />
            ?RRA:MAX:0.5:24:603 \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//每隔兩小時存一次資料的最大值</font><font color="#ffffff"><br />
            ?RRA:MAX:0.5:288:603&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//每隔一天存一次資料的最大值</font><font color="#ffffff"> <br />
            $LEE#</font></td>
        </tr>
    </tbody>
</table>
<hr />
<ul>
    <li><a name="6"></a><font color="#ff0000"><strong>抓取資料</strong></font> </li>
</ul>
<p>同上面所說，對於不會Shell Script或者是Perl..等可以處理字串的方法的人，這部份算是比較難的。 最好先花點時間先稍微閱讀一下此類資訊會比較好上手，以下提供一份不錯的Shell Script的教學文件<a href="http://www.study-area.org/cyril/scripts/scripts/">http://www.study-area.org/cyril/scripts/scripts/</a>。</p>
<p>以下為部分簡單的範例︰</p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">$LEE# snmpget -c public&nbsp; 192.168.0.1 ifInOctets.4&nbsp;<br />
            interfaces.ifTable.ifEntry.ifInOctets.4 = Counter32: 13526287</font></td>
        </tr>
    </tbody>
</table>
如果某台機器有安裝snmp的服務，則可用snmpget查詢此主機上面的資料，至於可以查詢到什麼資料端看那台機器所提供的MIB功能強不強大。上面的例子使用snmpget的指令嘗試抓取 192.168.0.1 這台主機的位址，"<font color="#0000ff">-c</font>"參數代表此台主機的通訊名稱，一般的主機預設為"<font color="#0000ff">public</font>"，但是也可以自訂，要了解某台主機的通訊名稱請向管理者詢問。"<font color="#0000ff">ifInOctets.4</font>"中的<font color="#0000ff">ifInOctets</font><font color="#000000">為查詢此台主機的輸入流量，後面的"</font><font color="#0000ff">.4</font><font color="#000000">"則代表第四個網路介面。</font>
<p><font color="#000000">下面的:</font><font color="#0000ff">interfaces.ifTable.ifEntry.ifInOctets.4 = Counter32: 13526287</font><font color="#008000"> </font><font color="#000000">為主機端回應的結果，因為我們要的資料為「</font><font color="#0000ff">13526287</font><font color="#000000">」(此值就是輸入流量)這個值，這時候就是字串處理函式發揮強大功能的時候啦！</font></p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">$LEE# snmpget -c public 192.168.0.1&nbsp; ifInOctets.4 | sed -e 's/.*ter32: \(.*\)/\1/'<br />
            13526287</font></td>
        </tr>
    </tbody>
</table>
<p>回傳值為「<font color="#0000ff">13526287</font>」，是的，這就是我們要的結果。 到底是什麼讓前面的那串文字不見而取的我們要的數值呢?&nbsp; 奧妙就在於後面的那<font color="#000000">串古怪的語法，「sed -e 's/.*ter32: \(.*\)/\1/'</font>」，不瞭解的話請自行翻閱Shell Script的教學文件，不然用法千百種講也講不完。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重要的是這只是我們往後的Script檔裡面的一個小小的範例，下面的範例將會附上一個完整的Script檔，您就能瞭解怎麼把這先抓回來的資料使用在RRDtool上了。</p>
<p>當然，您不一定要使用snmpget，也可以使用snmpwalk、tcpdump..等等抓資料回來分析，說誇張點，凡是有數字會「動」的東西都可以經過處理變成我們要的資料，然後畫成圖表。</p>
<hr />
<ul>
    <li><a name="7"></a><font color="#ff0000"><strong>更新RRD檔資料</strong></font> </li>
</ul>
<p>RRD的Update指令大概算是RRDtool裡面最簡單的指令了吧！</p>
<p>語法︰<font color="#0000ff">rrdtool update filename [--template|-t ds-name[:ds-name]...] N|timestamp:value[:value...]</font><br />
這個很好理解,基本上就是根據 DS來更新資料,如上述之lee.rrd,若有需要更新時</p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">$LEE# rrdtool update lee.rrd 1061811856:1199:0:821073&nbsp; </font><font color="#ffff00">// 後三個欄位分別代表(時間:欄位一值:欄位二值)</font></td>
        </tr>
    </tbody>
</table>
<p><br />
上面的 1061811856 即時間值,如果就是要現在的時間值,則可以 N 代表,但要轉換成秒值,通常我們都會以<font color="#0000ff">`date +%s`</font><font color="#000000">來轉換。可以試試看，在FreeBSD輸入</font><font color="#0000ff">`date +%s`:</font></p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">LEE# date +%s</font><br />
            <font color="#ffffff">1105334125&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//從1970/1/1 到現在的秒數</font></td>
        </tr>
    </tbody>
</table>
　
<p><font color="#ff0000">注</font>︰<font color="#000000">請注意在Linux下和FreeBSD下指令"</font><font color="#0000ff">date</font><font color="#000000">"的用法並不相同。如在Linux下"date -d"為轉換某日期成為秒數，而BSD下"date -d"則為系統設定時間，使用不當容易造成系統時間錯誤。</font></p>
<hr />
<ul>
    <li><a name="8"></a><font color="#ff0000"><strong>繪製圖表&nbsp;</strong></font> </li>
</ul>
<p>RRDtool繪圖語法︰(以下僅列出常用的)<br />
<font color="#0000ff">rrdtool graph image-filename</font><br />
<font color="#0000ff">-s</font> 繪圖資料的起始時間,預設是一天前,單位是"秒數"<br />
<font color="#0000ff">-e</font> 繪圖資料的結束時間,預設是現在,亦可使用 date 方式來達到前三天至昨天圖檔<br />
<font color="#0000ff">--no-minor</font> 不要副格線<br />
<font color="#0000ff">-t</font> 圖檔標題<br />
<font color="#0000ff">-v </font>Y 軸說明<br />
<font color="#0000ff">-w</font> 資料區的寬度,資料區指的是數據顯示的部份,而非說明或圖例<br />
<font color="#0000ff">-h</font> 資料區的高度<br />
<font color="#0000ff">-u</font> Y 軸正值高度<br />
<font color="#0000ff">-l </font>Y 軸負值高度<br />
-<font color="#0000ff">M</font> 自動調整畫圖的Y軸最大值</p>
<p><font color="#0000ff">DEF</font> 其語法為 <font color="#0000ff">DEF:vname:rrd_filename:DS_name:[AVERAGE|MAX..]</font><br />
這個有點像是上面的DS(Data Source)，亦即在圖表中宣告一個資料來源，必須先宣告，讓以下的圖從這邊取資料。<br />
<font color="#0000ff">CDEF</font> 一個虛擬的變數,就是把DEF的資料拿來做加工，其值為 DEF 的某些運算,其運算式需寫成<font color="#0000ff">後序</font><font color="#000000">，中間以逗號隔開。</font><br />
EX: a=1+3 寫成 a=1,3 +<br />
http=(input+output)/1024 寫成 http=input,output,+,1024,/<br />
<br />
<br />
<font color="#0000ff">LINE</font>函數其語法︰<font color="#0000ff">LINE{1|2|3}:vname[#rrggbb[:legend]]</font><font color="#000000">，用這條函式就是您想把資料用線條的方式表示，其中依照線條的粗細又可分為LINE1、LINE2、LINE3三種SIZE；</font><font color="#0000ff">vname</font><font color="#000000">這欄填的就是您為DEF這個地方宣告的名稱，這個名稱可自己隨意取；</font><font color="#0000ff">#rrggbb</font><font color="#000000">這裡填的就是你想要線條顯示出來的顏色，使用RGB代碼；</font><font color="#0000ff">legend</font><font color="#000000">裡面填的是AVERAGE、MAX等表示取值的方式</font><font color="#000000">。下面為例子︰</font></p>
<p><img height="239" src="http://im.nuk.edu.tw/~lee/rrdtool/image/2.gif" width="504" border="0"  alt="" /><br />
(此圖取自RRDtool完全攻略文章中)<br />
</p>
<p><font color="#0000ff">AREA</font>函數其語法︰<font color="#0000ff">AREA:vname[#rrggbb[:legend]]，</font><font color="#000000">用這條函式就是您想把資料用填充塊狀方塊的方式表示，其他後面的參數請參照LINE的用法，做出來的範例如下︰</font></p>
<p><img height="285" src="http://im.nuk.edu.tw/~lee/rrdtool/image/3.gif" width="575" border="0"  alt="" /><br />
(此圖取自RRDtool完全攻略文章中)<br />
</p>
<p><font color="#0000ff">STACK</font>函數其語法︰<font color="#0000ff">STACK:vname[#rrggbb[:legend]]</font><font color="#000000">，</font>則是畫出資料數值至其上的數值,也就是要有資料數值在 STACK 數值之上<font color="#000000">，用法同上兩個。</font><br />
如果使用 AREA/STACK 時需特別注意圖蓋圖的問題,一定要先畫<font color="#0000ff">大</font>的值,再畫<font color="#0000ff">小</font>的值,才會有層次的效果,不然,最大的數據若最後畫,會直接把小的資料蓋過去，導致小值無法顯示出來。<br />
<br />
<font color="#0000ff">COMMENT</font> 說明欄字,如上圖的的"Last Updated'字樣為使用<font color="#0000ff">COMMENT:"Last Updated"</font><font color="#000000">指令產生</font>，可以用 \n 等換行符號。<br />
GPRINT:<font color="#0000ff">GPRINT GPRINT:vname:CF:format vname</font> 即DEF 中的 vname,而 CF 看你要輸出的文字是AVERAGE/MAX/MIN/LAST 等數值,format 如同 printf 中的格式,<br />
做出來如下圖例︰</p>
<p><img height="376" src="http://im.nuk.edu.tw/~lee/rrdtool/image/4.gif" width="575" border="0"  alt="" /></p>
<hr />
<ul>
    <li><a name="9"><font color="#ff0000"><strong>其他少用的RRDtool的指令</strong></font> </li>
</ul>
<p><font color="#0000ff">rrdtool info</font><strong><font color="#ff0000"> </font></strong><font color="#000000"><em>rrdfile.rrd</em> <em>-</em> 顯示出rrd檔目前的資料儲存方式(如每幾分鐘球平均或算最大值....等等)。</font></p>
<p><font color="#0000ff">rrdtool dump</font><font color="#000000"> <em>rrdfile.rrd &gt; filename.xml&nbsp; - </em>把rrd二進位檔的資料以XML的資料格式匯出。</font></p>
<p><font color="#0000ff">rrdtool restore</font><font color="#000000"><em> filename.xml filename.rrd [--range-check|-r] - </em>把rrd匯出的XML檔匯入rrd的二進位檔內。</font></p>
<p><font color="#0000ff">rrdtool fetch</font><font color="#000000"> </font><font color="#000000"><em>rrdfile.rrd</em> CF [--resolution|-r resolution] [--start|-s start] [--end|-e end] - 抓取rrd資料檔內的特定資料。</font></p>
<p><font color="#0000ff">rrdtool tune</font> <font color="#000000"><em>rrdfile.rrd</em></font> [--heartbeat|-h ds-name:heartbeat] [--minimum|-i ds-name:min] [--maximum|-a ds-name:max] [--data-source-type|-d ds-name:DST] [--data-source-rename|-r old-name:new-name] - 調整rrd資料檔內的資料記錄方式。</p>
<p>以上指令詳細使用方式請參照官方網站︰</a><a href="http://www.rrdtool.org/">www.rrdtool.org</a></p>
<hr />
<ul>
    <li><a name="10"></a><font color="#ff0000"><strong>簡單實作範例</strong></font> </li>
</ul>
<p>寫了那麼多，還是來個簡單的從頭到尾的範例吧！</p>
<p>步驟一︰ 先在console下建立RRD檔，</p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">$LEE# rrdtool create test.rrd -s 300 DS:input:COUNTER:600:0:100000000 \&nbsp; </font><font color="#ffff00">//檔名請自訂，可以把test.rrd改掉</font><font color="#ffffff"><br />
            ?DS:output:COUNTER:600:0:100000000 \<br />
            ?RRA:AVERAGE:0.5:1:603 \<br />
            ?RRA:AVERAGE:0.5:6:603 \<br />
            ?RRA:AVERAGE:0.5:24:603 \<br />
            ?RRA:AVERAGE:0.5:288:603 \<br />
            ?RRA:MAX:0.5:1:603 \<br />
            ?RRA:MAX:0.5:6:603 \<br />
            ?RRA:MAX:0.5:24:603 \<br />
            ?RRA:MAX:0.5:288:603<br />
            $LEE# ls<br />
            test.rrd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//這樣就是建立成功了</font></td>
        </tr>
    </tbody>
</table>
<p>步驟二︰把下面的Script碼複製，用文書編輯器新建一個檔，把以下內容放到那個檔(假設叫做 test.sh)，並且依照黃色字的指示在相關變數裡面填入您自己主機的相關資料，填完後把黃色的註解刪除(不然執行時會出現錯誤)，最後打 "<font color="#0000ff">sh test.sh</font>"(看您的檔取什麼名稱)執行即可。</p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">#!/bin/sh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//宣告使用的shell為 Bourne Shell</font><font color="#ffffff">&nbsp;</font>
            <p><font color="#ffffff">#抓資料並更新<br />
            rrd_path="/root/rrd/test.rrd" </font><font color="#ffff00">//這個位址請指定為您存放rrd檔的目錄</font><font color="#ffffff"><br />
            rrd_data="192.168.0.1"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//這個IP位址請自行換成您要偵測的主機(目標主機須有執行:snmpd)<br />
            </font><font color="#ffffff">image_path="/root/rrd/html"&nbsp; </font><font color="#ffff00">//裡請把""裡面替換成您要存放圖檔的目錄</font><font color="#ffffff"><br />
            sec=300<br />
            while [ 1 ]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//這裡使用無窮迴圈跑此Script</font><font color="#ffffff"><br />
            do<br />
            input=`snmpget -c public $rrd_data ifInOctets.4 | sed -e 's/.*ter32: \(.*\)/\1/'`<br />
            output=`snmpget -c public $rrd_data ifOutOctets.4 | sed -e 's/.*ter32: \(.*\)/\1/'`<br />
            now=`date +%s`<br />
            echo "rrdtool update $rrd_path $now:$input:$output" &gt;&gt; test.cmd&nbsp;&nbsp; </font><font color="#ffff00">//紀錄update的資料</font><font color="#ffffff"><br />
            rrdtool update $rrd_path $now:$input:$output<br />
            <br />
            <br />
            #畫圖<br />
            rrdtool graph $image_path/test.png \<br />
            --title "Local Network" \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">\\換成您想要的圖檔標題</font><font color="#ffffff"><br />
            DEF:v1=$rrd_path:input:AVERAGE \<br />
            DEF:v2=$rrd_path:output:AVERAGE \<br />
            AREA:v1#FF0000:"Input" \<br />
            AREA:v2#00FF00:"Output" \<br />
            -v "Value"<br />
            </font><font color="#ffffff">sleep $sec<br />
            </font><font color="#ffffff">done</font>　</p>
            </td>
        </tr>
    </tbody>
</table>
<p>可以跑出一個圖，大概如下圖︰</p>
<p><img height="172" src="http://im.nuk.edu.tw/~lee/rrdtool/image/test.png" width="491" border="0"  alt="" /></p>
<p>上面只是個極為簡單的範例，事實上還有很多的參數可以設定，可以讓圖表更為精緻，您可以參考官方網站或者是下面的RRDtool完全攻略教學文件獲得進一步的資訊！</p>
<hr />
<ul>
    <li><font color="#ff0000"><strong><a name="11"></a>RRDtool備份</strong></font> </li>
</ul>
<p>聰明的您在看完上面的文章一定會想到，如果哪一天您的愛機遭遇不測(被雷打中?!)，那裡頭的寶貴資料不就全毀了? 其實在RRDtool中最重要的資料檔也不過是所謂的RRD資料檔，只要有這個檔圖就可以再畫，所以我們只要利用簡單的Shell Script就能達到備份的效果︰</p>
<p>以下假設您的電腦有兩顆硬碟，以下的範例示範如何定期的把資料備份到另外一個槽的資料夾︰</p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">#!/bin/sh<br />
            rrd_path="/root/rrd"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//RRD檔所在資料夾</font><font color="#ffffff"><br />
            rrd_file="a.rrd b.rrd c.rrd"&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//RRD的檔名，可能不只一個，此例為三個</font><font color="#ffffff"><br />
            dest="/home/backup"&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//備份檔預定存放的資料夾</font><font color="#ffffff"><br />
            <br />
            for data&nbsp; in $rrd_file<br />
            do<br />
            cp $rrd_path/$data&nbsp; $dest<br />
            done</font></td>
        </tr>
    </tbody>
</table>
<p>假設此Script 名稱為 backup.sh 放在/root/rrd資料夾底下，則我們可以在/etc/crontab這個檔或是打"crontab -e"裡面加入以下這行︰</p>
<table width="75%" border="0">
    <tbody>
        <tr>
            <td width="100%" bgcolor="#000000"><font color="#ffffff">*&nbsp;&nbsp;&nbsp; 12&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; root&nbsp;&nbsp;&nbsp; /root/rrd/backup.sh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#ffff00">//在每天中午十二點備份這些RRD檔到另外一個資料夾</font></td>
        </tr>
    </tbody>
</table>
<p>　</p>
<hr />
參考資料:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://phorum.study-area.org/viewtopic.php?t=18496">rrdtool完全攻略</a>　出處:酷學園　作者:Abelyang
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RRDtool 官方網站﹕<a href="http://www.rrdtool.org/">http://www.rrdtool.org</a></p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/257138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-02-28 13:12 <a href="http://www.blogjava.net/ruoyoux/articles/257138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在MySql上实现Replication(Master 与 Slave 数据同步) </title><link>http://www.blogjava.net/ruoyoux/articles/254408.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Thu, 12 Feb 2009 07:51:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/254408.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/254408.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/254408.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/254408.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/254408.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1： 首先确定Master和Slave的数据库版本，Master数据库的版本不能高于Slave数据的版本。这里我是使用MySql 5.0.27 作为Master数据库，MySql 6.0.3（alpha）作为Slave进行测试。&nbsp;2：首先修改Master数据库的配置文件my.ini (windows), /etc/my.cnf(linux)里[mysqld]datad...&nbsp;&nbsp;<a href='http://www.blogjava.net/ruoyoux/articles/254408.html'>阅读全文</a><img src ="http://www.blogjava.net/ruoyoux/aggbug/254408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-02-12 15:51 <a href="http://www.blogjava.net/ruoyoux/articles/254408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正则表达式详解（Perl）</title><link>http://www.blogjava.net/ruoyoux/articles/253084.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Tue, 03 Feb 2009 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/253084.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/253084.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/253084.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/253084.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/253084.html</trackback:ping><description><![CDATA[<div><strong>定义</strong>：正则表达式是一种字符串模式，可用来和字符串进行匹配。匹配可能成功，也可能失败。许多UNIX命令，包括grep, sed, awk, ed, vi, emacs都有正则表达式的功能。Perl也有这种功能。Python也具有这种功能。</div>
<div></div>
<div><strong>简单示例</strong>：</div>
<div>例如：</div>
<div style="text-indent: 21.75pt;"><em><span style="color: #00ccff;">grep abd readme.file &gt; result.tx</span></em><span style="color: #00ccff;">t</span></div>
<div>则Perl中，写成</div>
<div style="text-indent: 21.75pt;"><span style="color: blue;">if(/abc/)</span></div>
<div style="text-indent: 21.75pt;"><span style="color: blue;">{</span></div>
<div style="text-indent: 21.75pt;"><span style="color: blue;">&nbsp;print $_;</span></div>
<div style="text-indent: 21.75pt;"><span style="color: blue;">}</span></div>
<div>在Perl中，正则表达式用斜线标记，以代表斜线之间的内容是个正则表达式。当表达式北斜线包围时，Perl会拿$_和它作比较，以判断条件的真假。</div>
<div>&nbsp;&nbsp; <em><span style="color: blue;">while(&lt;&gt;) {</span></em></div>
<div style="text-indent: 27pt;"><em><span style="color: blue;">if (/abc/) {</span></em></div>
<div style="text-indent: 27pt;"><em><span style="color: blue;">&nbsp;&nbsp;&nbsp; print $_;</span></em></div>
<div style="text-indent: 27pt;"><em><span style="color: blue;">}</span></em></div>
<div style="text-indent: 10.5pt;"><em><span style="color: blue;">}</span></em></div>
<div style="text-indent: 10.5pt;">这个程序片断能读入某文件的所有内容，并进行匹配。</div>
<div style="text-indent: 10.5pt;">&nbsp;<span style="color: aqua;">grep &#8220;ab*c&#8221; readme.file &gt; result</span></div>
<div style="text-indent: 10.5pt;">&nbsp;<span style="color: blue;">while( &lt;&gt; )</span></div>
<div style="text-indent: 10.5pt;"><span style="color: blue;">&nbsp;{</span></div>
<div style="text-indent: 10.5pt;"><span style="color: blue;">&nbsp;&nbsp;&nbsp; if (/ab*c/) {</span></div>
<div style="text-indent: 10.5pt;"><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print $_;</span></div>
<div style="text-indent: 31.5pt;"><span style="color: blue;">}</span></div>
<div><span style="color: blue;">&nbsp;&nbsp; }</span></div>
<div>&nbsp; 以上程序片断表示以a开头，后面跟0个以上的b,最后以c结尾。</div>
<div>&nbsp;替代运算符以s字母开头，跟正则表达式，再跟替代的运算符号。</div>
<div>&nbsp;&nbsp; <span style="color: blue;">s/ab*c/def/</span></div>
<div>&nbsp; 变量是$_会跟正则表达式(ab*c)做比较。进行匹配。</div>
<div>&nbsp;<strong>类型</strong>：一个&#8220;正则表达式&#8221;就是一种类型pattern。分为单字符类型和多字符类型。</div>
<div><strong>单字符类型</strong>：单字符类型是最常见和最常用的类型。如a。单字符类型&#8221;.&#8221;能跟除换行符号(\n)的任何字符匹配。如</div>
<div style="text-indent: 27pt;"><span style="color: blue;">/a./</span></div>
<div>&nbsp;会和任何长度为二，且开头是a的字符串匹配。除了&#8221;a\n&#8221;外。</div>
<div>&nbsp;<strong>字符类</strong>：(character class)，写法是左右两个中括号([])，内放字符。即字符串对应此类型的地方，若出现唯一一个符合括号中列出的字符，就算符合。</div>
<div>&nbsp;<span style="color: blue;">/[abcde]/</span></div>
<div><span style="color: blue;">&nbsp;/[aeiouAEIOU]/</span></div>
<div>若在中括号中放[或者]，则需要在前面加反斜杠。如果想表示一段范围，则可以用破折号(dash-)连接。想表示破折号，则前面也必须加反斜杠。</div>
<div><span style="color: blue;">[0123456789]</span></div>
<div><span style="color: blue;">[0-9]</span></div>
<div><span style="color: blue;">[0-9\-]</span></div>
<div><span style="color: blue;">[a-zA-Z]</span></div>
<div>也可以用&#8220;反例&#8221;表示字符类别，只要在原来的写法前加上&#8220;^&#8221;即可。此种类型的意思是任何不在此类别内的单一字符才算上匹配。</div>
<div><span style="color: blue;">[^0-9]</span></div>
<div><span style="color: blue;">[^aeiouAEIOU]</span></div>
<div><span style="color: blue;">[^\^]</span></div>
<div>预定义的字符类别</div>
<table style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">字符</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">类别</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">反例</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">反例类别</div>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">\d</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">[0-9]</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">\D</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">[^0-9]</div>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">\w</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">[a-zA-Z]</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">\W</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">[^a-zA-Z]</div>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">\s</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">[\r\t\n\f]</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">\S</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 142px; background-color: transparent;" valign="top">
            <div align="center">[^\r\t\n\f]</div>
            </td>
        </tr>
    </tbody>
</table>
<div><span style="color: blue;">[\da-fA-F]&nbsp;#</span><span style="color: blue;">十六进制数字</span></div>
<div><strong>类型组合</strong>：grouping pattern就是将正则表达式组合起来用。</div>
<div><strong>系列</strong>：sequence, 如&#8221;abc&#8221;</div>
<div><strong>重复符号</strong>：multiplier，如星号(*)表示出现零次以上；加号(+)则表示出现一次以上；问号(?)则表示出现零次或一次。</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">/fo+ba?r/</span></div>
<div>以上的类型都是贪婪型的greedy。</div>
<div style="text-indent: 21.75pt;"><span style="color: blue;">$_ = &#8220;fred xxxxxxxxx barney&#8221;;</span></div>
<div style="text-indent: 21.75pt;"><span style="color: blue;">s/x+/boom/</span></div>
<div><strong>一般重复符号</strong>：(general multiplier)，写法是一对大括号中放一个或两个数字，如/x{5, 10}/，表示x出现5到10次；/x{5,}/表示出现5次以上；/x{5}/表示刚好5个x；/x{0,5}/意思就是&#8221;0到5个&#8221;</div>
<div><span style="color: fuchsia;">正则表达式如出现两个重复符号，必须遵循&#8220;最左边最贪心&#8221;</span><span style="color: fuchsia;">(leftmost is greediest)</span><span style="color: fuchsia;">的规则。</span></div>
<div>$_ = &#8220;a&nbsp;xxx c xxxxxxxxxx c xxx d&#8221;;</div>
<div>/a.*c.*d/;</div>
<div>以这个例子，第一个&#8220;.&#8221;就会和第二个c之前所有的字符符合。可以在重复符号后面加上问号，让它变得&#8220;不贪心&#8221;(nongreedy)。</div>
<div><span style="color: blue;">$_=&#8221;a xxx&nbsp;c xxxxxx c xxx d&#8221;;</span></div>
<div><span style="color: blue;">/a.*c?.*d/</span></div>
<div>把字符串和正则表达式再该一下：</div>
<div>$_=&#8221;a xxx ce xxxxxxx ci xxx d&#8221;;</div>
<div>/a.*ce.*d/</div>
<div>这个例子中.*如果匹配到第二个c，则e没有办法匹配。故Perl会重试，降低了效率。实际上只要加个&#8221;?&#8221;就能让Perl少做很多事。</div>
<div><strong>把括号当记忆空间</strong>：另外一个组合符号，是前后包围任何类型的括号对(parentheses pair)。括号不会改变类型匹配的情形，不过可以把匹配的部分记录下来，以后参考。调用记住部分，写法是在反斜线后面加上数字。</div>
<div>&nbsp;&nbsp; <span style="color: blue;">/fred(.)barney\1/;</span></div>
<div>&nbsp; 会和fredxbarneyx匹配，不会和fredxbarneyy匹配。但是/fred.barney./和两个字符串都匹配。</div>
<div>其中\1代表正则表达式中，第一个用括号括起来的部分。依次有\2, \3&#8230;</div>
<div>/a(.)b(.)c\2d\1/;</div>
<div>可以在括号中放入一个以上的字符。如/a(.*)b\1c/;</div>
<div><strong>选项符号</strong>：还有一种组合符号称为选项符号(alternation)，如&#8220;a|b|c&#8221;。选项可以不只一个字符，如/song|blue/。</div>
<div><strong>定位类型</strong>：anchor pattern定位类型有好几种。定位类型\，表示目标字符串的这个地方必须是文字边界(word boundary)。所谓&#8220;文字边界&#8221;就是指符合\w或\W的字符，二个中间的位置；或者界于任何符合\w的字符，与字符串开头（或结尾）中间的位置。</div>
<div><span style="color: blue;">/fred\b/</span><span style="color: blue;">；</span><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #</span><span style="color: blue;">会和</span><span style="color: blue;">fred</span><span style="color: blue;">匹配，不会和</span><span style="color: blue;">Frederick</span><span style="color: blue;">匹配</span></div>
<div><span style="color: blue;">/\bmo/</span><span style="color: blue;">；</span><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #</span><span style="color: blue;">会和</span><span style="color: blue;">moe</span><span style="color: blue;">和</span><span style="color: blue;">mole</span><span style="color: blue;">匹配，不会和</span><span style="color: blue;">Elmo</span><span style="color: blue;">匹配</span></div>
<div><span style="color: blue;">/\bFred\b/</span><span style="color: blue;">；</span><span style="color: blue;">&nbsp;&nbsp; #</span><span style="color: blue;">会和</span><span style="color: blue;">Fred</span><span style="color: blue;">匹配，但</span><span style="color: blue;">Frederick</span><span style="color: blue;">或</span><span style="color: blue;">alFred</span><span style="color: blue;">都不匹配</span></div>
<div><span style="color: blue;">/\b\+\b/</span><span style="color: blue;">；</span><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp; #</span><span style="color: blue;">会和</span><span style="color: blue;">x+y</span><span style="color: blue;">匹配，不会和</span><span style="color: blue;">++</span><span style="color: blue;">或</span><span style="color: blue;">+</span><span style="color: blue;">匹配</span></div>
<div>另一个定位类型\B所在之处就不一定是文字边界，如</div>
<div><span style="color: blue;">/\bFred\B/</span><span style="color: blue;">；</span><span style="color: blue;">&nbsp;&nbsp; #</span><span style="color: blue;">会和</span><span style="color: blue;">Frederich</span><span style="color: blue;">匹配，但</span><span style="color: blue;">Fred Flintstone</span><span style="color: blue;">不匹配</span></div>
<div>还有两种类型，代表字符串的开头或结尾的前一个字符。&#8220;^&#8221;会和字符串的&#8220;开头&#8221;匹配。^a会匹配以a开头的字符串，不过a^会和&#8221;a&#8221;和&#8221;
^&#8221;这两个字符串匹配。即&#8221;^&#8221;失去了特别的意义
。如果想表示字符串开头是有个^号，则用\^即可。另外一个定位类型是&#8221;$&#8221;，不过表示字符串结尾。c$表示最后出现的字符是c的那个字符串。表示$这个
字符，用\$表示。</div>
<div><strong>优先级</strong>：</div>
<table style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div align="center">名称</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div align="center">表示法</div>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div>括号(parentheses)</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div>() (?:)</div>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div>重复运算符(multiplier)</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div>? + * {m, n} ?? +? *? {m, n}?</div>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div>序列和定位符号(sequence and anchoring)</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div>abc^$\A\Z(?=) (?!)</div>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div>选项符号(alternation)</div>
            </td>
            <td style="padding: 0cm 5.4pt; width: 284px; background-color: transparent;" valign="top">
            <div>|</div>
            </td>
        </tr>
    </tbody>
</table>
<div>&nbsp;<span style="color: blue;">abc*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #</span><span style="color: blue;">会和</span><span style="color: blue;">ab, abc, abcc, abccc, abcccc</span><span style="color: blue;">匹配</span></div>
<div><span style="color: blue;">&nbsp;(abc)*</span></div>
<div><span style="color: blue;">&nbsp;^x|y</span></div>
<div><span style="color: blue;">&nbsp;^(x|y)</span></div>
<div><span style="color: blue;">&nbsp;a|bc|d</span></div>
<div><span style="color: blue;">&nbsp;(a|b)(c|d)</span></div>
<div><span style="color: blue;">&nbsp;(song|blue)bird</span></div>
<div><strong>=~</strong><strong>运算符：</strong>如果拿来匹配的字符串，不放在$_变量，则可以用&#8221;=~&#8221;运算符来解决：可把正则表达式放在运算符右侧，左侧则是想比较的字符串。即把正则表达式的默认目标转向运算符的左边运算单元。</div>
<div><span style="color: blue;">$a = &#8220;hello world!&#8221;;</span></div>
<div><span style="color: blue;">$a =~ /^he/;</span></div>
<div><span style="color: blue;">$a=~/(.)\1/;</span></div>
<div><span style="color: blue;">if($a=~/(,)\1/)</span></div>
<div>任何能传回标量字符串值的语句，都可以当作=~运算符的左边单元。如，如</div>
<div>print &#8220;any last request?&#8221;;</div>
<div>if( =~ /^[yY]/) {</div>
<div style="text-indent: 21.75pt;">print &#8220;And just what might that request be&#8221;;</div>
<div style="text-indent: 21.75pt;">print &#8220;Sorry, I&#8217;m unable to do that.\n&#8221;</div>
<div>}</div>
<div><strong>忽略大小写</strong>：grep有-I这个旗标，意思是忽略大小写；在Perl中提供了类似的方法：在正则表达式第二个斜线之后写上I即可。如/somepattern/i。</div>
<div>&nbsp;&nbsp; print &#8220;any last request?&#8221;;</div>
<div>&nbsp;&nbsp; if ( =~ /^y/i)</div>
<div>&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp; }</div>
<div><strong>指定界限符号</strong>：正则表达式前后用斜线包起来，斜线叫分界符号(delimiter)，如果想在正则表达式表示斜线这个&#8220;字符&#8221;，在前面加反斜线。</div>
<div>&nbsp;$path =</div>
<div>&nbsp;if($path =~ /^\/usr\/etc/) {</div>
<div>}</div>
<div>Perl允许设计者自行指定分界符合。可用任何－个非字母、非数字、非空白的字符为分界符号，方法是在第一次使用之前写&#8221;m&#8221;。</div>
<div>&nbsp;<span style="color: blue;">/^\/usr\/etc/</span></div>
<div><span style="color: blue;">&nbsp;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#64;&#37;&#53;&#69;&#47;&#117;&#115;&#101;&#114;&#47;&#101;&#116;&#99;&#64;">m@^/user/etc@</a></span></div>
<div><span style="color: blue;">&nbsp;m#^/usr/etc#</span></div>
<div>&nbsp;<strong>内插变量</strong>：正则表达式也可以内插变量。</div>
<div>&nbsp;$what = &#8220;bird&#8221;</div>
<div>&nbsp;$sentence = &#8220;Every good bird does fly.&#8221;;</div>
<div>&nbsp;if($sentence =~ /\b$what\b/)</div>
<div>&nbsp;{</div>
<div style="text-indent: 21.75pt;">print &#8220;The sentence contains the word $what\n&#8221;;</div>
<div>&nbsp;}</div>
<div>&nbsp;下面的例子稍微复杂一些：</div>
<div>&nbsp;$sentence = &#8220;Every good bird does fly.&#8221;;</div>
<div>&nbsp;print &#8220;What should I look for?&#8221;;</div>
<div>&nbsp;$what = ;</div>
<div>&nbsp;chomp($what);</div>
<div>&nbsp;if($sentence =~ /$what/)</div>
<div>&nbsp;{</div>
<div style="text-indent: 27pt;">print &#8220;I saw $what in $sentence.\n&#8221;;</div>
<div>&nbsp;}</div>
<div>&nbsp;else</div>
<div>&nbsp;{</div>
<div style="text-indent: 32.25pt;">print &#8220;nope&#8230; didn&#8217;t find it.\n&#8221;;</div>
<div>&nbsp;}</div>
<div><strong>特别的只读变量</strong>：匹配成功后，名为$1, $2, $3&#8230;的这些变量，它们的值被分别设为\1,\2,\3&#8230;之值。</div>
<div>&nbsp;&nbsp; <span style="color: blue;">$_ = &#8220;this is a test&#8221;;</span></div>
<div><span style="color: blue;">&nbsp;&nbsp; /(\w+)W+(\w+)/</span><span style="color: blue;">；</span><span style="color: blue;">#</span><span style="color: blue;">和头两个文字匹配；现在</span><span style="color: blue;">$1</span><span style="color: blue;">是</span><span style="color: blue;">&#8221;this&#8221;</span><span style="color: blue;">，</span><span style="color: blue;">$2</span><span style="color: blue;">是</span><span style="color: blue;">&#8221;is&#8221;</span><span style="color: blue;">。</span></div>
<div>也可以在列表环境下，一次取得所有匹配的片断。</div>
<div>&nbsp;&nbsp; $_=&#8221;this is a test.&#8221;;</div>
<div>&nbsp;($first, $second) = /(\w+)W+(\w+)/;</div>
<div>其他预定义的只读变量包括：&#8221;<span style="color: fuchsia;">$&amp;&#8221;</span>，代表字符串中匹配正则表达式的部分；&#8221;<span style="color: fuchsia;">$`&#8221;</span>代表匹配处之前的部分；&#8221;<span style="color: fuchsia;">$&#8217;&#8221;</span>代表匹配处之后的部分。</div>
<div>&nbsp;$_=&#8221;this is a sample string.&#8221;;</div>
<div>&nbsp;/sa.*le/;&nbsp;&nbsp; #和sample匹配。s`是&#8221;this is a &#8220;，$&amp;是&#8221;sample&#8221;，$&#8217;是&#8221;string&#8221;</div>
<div><strong>替代运算符</strong>：s/old-regex/new-string/这样的用法是最简单的一种替代运算符。如果想让替代运算符在每个匹配的地方取代，而非仅作用在第一个匹配处，在运算符加g.</div>
<div>&nbsp;<span style="color: blue;">$_=&#8221;foot fool buffoon&#8221;;</span></div>
<div><span style="color: blue;">&nbsp;s/foo/bar/g;</span></div>
<div>替代运算符也可以内插变量，像这样：</div>
<div>&nbsp;<span style="color: blue;">$_=&#8221;hello, world&#8221;;</span></div>
<div><span style="color: blue;">&nbsp;$new = &#8220;goodbye&#8221;;</span></div>
<div><span style="color: blue;">&nbsp;s/hello/$new/;</span></div>
<div>可以在替代运算符里用字符类型，就不会和固定的字符匹配了：</div>
<div>&nbsp;$_=&#8221;this is a test&#8221;;</div>
<div>&nbsp;s/(\w+) /&lt;$1&gt;/g;&nbsp;#$_现在是&nbsp;&nbsp;
<p>&nbsp;&nbsp;</p>
<div>替代运算符可以加上i,代表忽略大小写，如果已经有g了，则i可以出现在g前后。斜线还可以用其他符号代替。s#fred#barney#;替代运算符也可以用=~改变作用的目标。</div>
<div>split和join函数：正则表达式可以把字符串分成许多字段。split函数可以这样做。而join函数则可以把这些片断组合起来。
split函数有两个参数，分别是正则表达式和字符串，它会寻找字符串中匹配正则表达式的部分，其他不匹配的部分会依序用列表值方式传回。</div>
<div><span style="color: blue;">$line= &#8220;merlyn::118:10:Randal:/home/merlyn:/urs/bin/perl &#8220;;</span></div>
<div><span style="color: blue;">@fields = split(/:/, $line);</span></div>
<div>如果要匹配一个以上的:则用：</div>
<div><span style="color: blue;">@fields = split(/:+, $line);</span></div>
<div>变量$_是split函数的第二个参数的默认值：</div>
<div><span style="color: blue;">$_=&#8221;some string&#8221;;</span></div>
<div><span style="color: blue;">@words =split(/&nbsp;/);</span></div>
<div>由于参数字符串内没有连续的空白字符，结果会是空字符串。理想的写法是/&nbsp;+/, /\s+/和&#8221;一个以上&#8220;的空白字符匹配。这是第一个参数的默认值。</div>
<div><span style="color: blue;">@words = split;</span><span style="color: blue;">用空白字符分割</span><span style="color: blue;">$_</span><span style="color: blue;">。</span></div>
<div><span style="color: blue;">$line=&#8221;merlyn::118:10:Randa;:/home/merlyn:&#8221;);</span></div>
<div><span style="color: blue;">($name,$password,$uid,$gid,$gcos,$home,$shell)=split(/:/,$line);</span></div>
<div>join函数跟split函数对应，该函数用第一个参数字符串当作&#8221;胶&#8221;，把第二个参数里面的值一个个&#8220;粘&#8220;起来。</div>
<div>$bigstring=join($glue,@list);</div>
</div>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/253084.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-02-03 15:19 <a href="http://www.blogjava.net/ruoyoux/articles/253084.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Synchronizing Large Applications</title><link>http://www.blogjava.net/ruoyoux/articles/252319.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Thu, 22 Jan 2009 04:17:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/252319.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/252319.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/252319.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/252319.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/252319.html</trackback:ping><description><![CDATA[<h2 class="sol">Synchronizing Large Applications</h2>
<p>When your environment contains large applications to synchronize or
available memory is constrained, you can adjust the JVM options to limit memory
usage. This adjustment reduces the possibility of receiving out of memory
errors. The instance synchronization JVM uses default settings, but you can
configure JVM options to change them.</p>
<p>Set the JVM options using the <tt>INSTANCE-SYNC-JVM-OPTIONS</tt> property.
The command to set the property is:</p>
<pre>asadmin set <br />
domain.node-agent.<var>node_agent_name</var>.property.INSTANCE-SYNC-JVM-OPTIONS="<var>JVM_options</var>"</pre>
<p>For example:</p>
<pre>asadmin set <br />
domain.node-agent.node0.property.INSTANCE-SYNC-JVM-OPTIONS="-Xmx32m -Xss2m"</pre>
<p>In this example, the node agent is <tt>node0</tt> and the
JVM options are <tt>-Xmx32m -Xss2m</tt>.</p>
<p>For more information, see <a href="http://java.sun.com/docs/hotspot/VMOptions.html"><tt>http://java.sun.com/docs/hotspot/VMOptions.html</tt></a>.</p>
<br />
<p>Another example:</p>
<p>bin/asadmin set domain.node-agent.agent2.property.INSTANCE-SYNC-JVM-OPTIONS="-Xmx512m"<br />
<br />
</p>
<p><strong>Note &#8211; </strong>
</p>
<p>Restart the node agent after changing the INSTANCE-SYNC-JVM-OPTIONS
property, because the node agent is not automatically synchronized when a
property is added or changed in its configuration.</p>
<br />
<p><br />
</p>
<h3 class="sol">Using the doNotRemoveList Flag</h3>
<p>If your application requires to store and read files in the directories
(applications, generated, docroot, config, lib, java-web-start) that are synchronized
by the Application Server, use the <tt>doNotRemoveList</tt> flag.
This attribute takes a coma-separated list of files or directories. Your application
dependent files are not removed during server startup, even if they do not
exist in the central repository managed by DAS. If the same file exists in
the central repository, they will be over written during synchronization.</p>
<p>Use the <tt>INSTANCE-SYNC-JVM-OPTIONS</tt> property to pass
in the doNotRemoveList attribute.</p>
<p>For example:</p>
<p>
<tt>&lt;node-agent name="na1" ...&gt;</tt>
</p>
<p>
<tt>...</tt>
</p>
<p>
<tt>&lt;property name="INSTANCE-SYNC-JVM-OPTIONS"
value="-Dcom.sun.appserv.doNotRemoveList=applications/j2ee-modules/&lt;webapp_context&gt;/logs,generated/mylogdir"/&gt;</tt>
</p>
<p>
<tt>&lt;/node&#8211;agent&gt;</tt>
</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/252319.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-01-22 12:17 <a href="http://www.blogjava.net/ruoyoux/articles/252319.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How to Automate Secure File Synchronization using SSH and rsync</title><link>http://www.blogjava.net/ruoyoux/articles/252074.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Tue, 20 Jan 2009 09:18:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/252074.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/252074.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/252074.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/252074.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/252074.html</trackback:ping><description><![CDATA[<h1>How to Automate Secure File Synchronization using SSH and rsync </h1>
<p>
Tom Hilinski <br />
Natural Resource Ecology Laboratory, <br />
Colorado State University<br />
Last updated: Dec 2008
</p>
<h2>
Introduction
</h2>
<p>
In order to automate file transfers between computers without a password, a private-public
key identification key simplifies the process. This is useful, for instance,
when using rsync to synchronize files in local and remote directories. For
instance, after editing files on your local Linux desktop or Microsoft Windows
laptop, you want to automatically update the files on the office computer with
your modified files. In this case, a utility such as rsync can be used to do
the update without prompting you for a password on the office computer.
</p>
<p>
The process of creating the key is described here in the context of using rsync
on a local Windows computer with Cygwin installed. Use the Cygwin setup program
to install SSH, rsync, and Bash. Here, I assume that the remote computer, say,
your office server, is running Linux, and you have an account on it with the
user name <em>yourUserName</em>.
</p>
<p>
In the examples below, command lines begin with a $ character, comment lines
begin with a # character, while text beginning without either is written to
the console display. Example text that is italicized means you substitute your
own information there; for example, <tt><em>yourUserName</em></tt> is replace by
your actual user name.
</p>
<h2>
Create a Key
</h2>
<p>
On your local Windows computer, open a Bash shell console window. If you don't
have a directory named .ssh create one by using SSH to connect to your office
computer for the first time. You will be prompted to accept the key.
</p>
<blockquote>
<pre><tt>$ ls -d .ssh<br />
# if the directory does not exist, run ssh<br />
$ ssh <em>yourUserName</em>@calypso.nrel.colostate.edu</tt></pre>
</blockquote>
<p>
Go into the .ssh directory and create a key. This key will have two files, a
private file and a public file. When prompted, do not enter a password or passphrase.
</p>
<blockquote>
<pre><tt>$ ssh-keygen -t dsa -b 1024 -f <em>yourUserName</em>-rsync-key<br />
Generating public/private dsa key pair.<br />
Enter passphrase (empty for no passphrase):<br />
Enter same passphrase again:<br />
Your identification has been saved in <em>yourUserName</em>-rsync-key.<br />
Your public key has been saved in <em>yourUserName</em>-rsync-key.pub.<br />
The key fingerprint is:<br />
(a long string of hexadecimal digits)</tt></pre>
</blockquote>
<p>
Check the permissions on your key files (e.g.,<tt> ls -l</tt>).  The permissions
should be 600 (or <tt>rw-----</tt>).
</p>
<p>
On your office computer, make sure you have in your home directory, a subdirectory
named .ssh (note the leading dot).
</p>
<blockquote>
<pre><tt>$ ssh <em>yourUserName</em>@calypso.nrel.colostate.edu<br />
$ ls -d .ssh<br />
# If this directory doesn't exist, create it:<br />
$ mkdir .ssh<br />
# Make sure the permissions are secure:<br />
$ chmod 700 .ssh</tt></pre>
</blockquote>
<p>
Now, log off your office computer.
</p>
<p>
Next, copy the public key file to your office
computer, log onto that computer, then append the key file to the SSH file
containing keys it knows about.
</p>
<blockquote>
<pre><tt># Copy the public key to your office computer:<br />
$ scp <em>yourUserName</em>-rsync-key.pub <em>yourUserName</em>@calypso.nrel.colostate.edu:/home/nrel/<em>yourUserName</em>/.ssh/<br />
# Log on to the remote computer:<br />
$ ssh <em>yourUserName</em>@calypso.nrel.colostate.edu<br />
# If your are not in a bash shell, then start one:<br />
$ bash<br />
# If the key file does not exist, create it:<br />
$ if [ ! -f authorized_keys ]; then touch authorized_keys; chmod 600 authorized_keys; fi<br />
# Append your new public key to the key file:<br />
$ cat <em>yourUserName</em>-rsync-key.pub &gt;&gt; authorized_keys<br />
$ rm <em>yourUserName</em>-rsync-key.pub </tt></pre>
</blockquote>
<p>
Your key is now ready to use with rsync. Optionally, you can restrict the use
of the key to an IP address and a particular process (e.g., rsync). To restrict
the key to rsync, create the file listed in Appendix A in your ~/.ssh directory on your
office computer. You can use a text editor to paste that text in.
Then set the permissions so no one else can read it. For example:
</p>
<blockquote>
<pre><tt># Use vi to create the file; paste in the script from Appendix A.<br />
$ vi restrict-to-rsync<br />
$ chmod 700 restrict-to-rsync</tt></pre>
</blockquote>
<p>
Next, edit the file <tt>authorized_keys</tt> so that the line with your key (the
last line, since the key was just appended to the file) begins with a command
to run that script. The command points to the full path of the script file.
The line originally began with:
</p>
<blockquote>
<pre><tt>ssh-dss AAAAB3...</tt></pre>
</blockquote>
<p>After inserting the script command, the line starts with:</p>
<blockquote>
<pre><tt><font color="#800000">command="/home/nrel/<em>yourUserName</em>/.ssh/restrict-to-rsync" </font>ssh-dss AAAAB3...</tt></pre>
</blockquote>
<h2>
Using rsync With SSH and Your Key
</h2>
<p>
Test the use of your new key by copying a junk file from your local computer
to your office computer. Here, the local file is <tt>junk.txt</tt> and the
remote directory in your office computer is <tt>tmp</tt>, and the direction
of transfer is local-to-remote. Give SSH the name of your private key file
on your local computer, including its path, using the following form:
</p>
<blockquote>
<pre><tt>rsync -auvz -e "ssh -i <em>private-key-file</em>" <em>source</em> <em>destination</em></tt></pre>
</blockquote>
<p>Here, <em>source</em> is a file or a directory, and <em>destination</em> has the form
<tt><em>yourUserName</em>@<em>remote-computer</em>:/<em>remote-path</em></tt>
</p>
<p>
A real example, using the file names from the previous examples, is:
</p>
<blockquote>
<pre><tt>rsync -auvz -e "ssh -i /home/<em>yourUserName</em>/.ssh/<em>yourUserName</em>-rsync-key" junk.txt <em>yourUserName</em>@calypso.nrel.colostate.edu</tt></pre>
</blockquote>
<p>
The rsync flags <tt>-auvz</tt> specify "archive", "update", "verbose
messages",
and "compress
files for transfer", respectively. "Update" means that files on
the destination that are newer than your local files are not overwritten. The "-e" flag
tells rsync the SSH command.
</p>
<p>
If you want details on what SSH is doing, add "-v" to the ssh options. To run
rsync quietly, remove the "-v" option from both rsync and SSH option list.
</p>
<p>
To reverse the synchronization so the remote file is updated on your local computer,
reverse the source and destinations.
</p>
<p>
You can store your rsync commands that you use all the time in a script file.
Keep this script with your project files or in a script directory that is specified
in your PATH environment variable.
</p>
<h2>
Additional Information
</h2>
<p>
rsync document:
<a href="http://rsync.samba.org/ftp/rsync/rsync.html" target="_blank">http://rsync.samba.org/ftp/rsync/rsync.html</a>
</p>
<p>
rsync web site: <a href="http://rsync.samba.org/" target="_blank">http://rsync.samba.org/</a>
</p>
<h2>
Acknowledgements
</h2>
<p>
Many online sources provided the information I used to create this process. A
particularly succinct source was
<a href="http://troy.jdmz.net/rsync/index.html" target="_blank">http://troy.jdmz.net/rsync/index.html</a> provided
the basis of the script in Appendix A. Thanks to all.
</p>
<h2>
Appendix A: File <tt>restrict-to-rsync</tt>
</h2>
<p> The following shell script checks that rsync is the process attempting to connect.
If it is not, the script fails, and SSH also fails.
A log file named <tt>validate-rsync.log</tt> is created or appended to with each connection.
</p>
<blockquote>
<pre><tt>#!/bin/sh<br />
logfile=/home/nrel/<em>yourUserName</em>/.ssh/restrict-to-rsync.log<br />
case "$SSH_ORIGINAL_COMMAND" in<br />
*\&amp;*)<br />
echo `date` "- SSH connection rejected" &gt;&gt; $logfile<br />
;;<br />
*\(*)<br />
echo `date` "- SSH connection rejected" &gt;&gt; $logfile<br />
;;<br />
*\{*)<br />
echo `date` "- SSH connection rejected" &gt;&gt; $logfile<br />
;;<br />
*\;*)<br />
echo `date` "- SSH connection rejected" &gt;&gt; $logfile<br />
;;<br />
*\&lt;*)<br />
echo `date` "- SSH connection rejected" &gt;&gt; $logfile<br />
;;<br />
*\`*)<br />
echo `date` "- SSH connection rejected" &gt;&gt; $logfile<br />
;;<br />
*\|*)<br />
echo `date` "- SSH connection rejected" &gt;&gt; $logfile<br />
;;<br />
rsync\ --server*)<br />
{<br />
echo `date` "- SSH connection accepted" &gt;&gt; $logfile<br />
$SSH_ORIGINAL_COMMAND<br />
}<br />
;;<br />
*)<br />
echo `date` "- SSH connection rejected" &gt;&gt; $logfile<br />
;;<br />
esac</tt></pre>
</blockquote>
<hr />
<img src ="http://www.blogjava.net/ruoyoux/aggbug/252074.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-01-20 17:18 <a href="http://www.blogjava.net/ruoyoux/articles/252074.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Remote Backups With Rsync</title><link>http://www.blogjava.net/ruoyoux/articles/252067.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Tue, 20 Jan 2009 08:29:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/252067.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/252067.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/252067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/252067.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/252067.html</trackback:ping><description><![CDATA[<center>
<h1>Remote Backups With Rsync</h1>
<p><br />
</p>
</center>
<p>
In this article we explain how to automate the backup of files on remote machines to a centralized server using rsync.
</p>
<p>
rsync is a command line utility that is used to synchronize files
between two computers over a network to synchronize files between two
filesystems. It was written as a replacement for rcp but with many new
features. For example it uses an algorithm that will only transfer
files that have been modified. SSH will be used to authenticate between
the machines and to encrypt the network traffic. </p>
<p>
The situation: We have four machines named: server, machine1, machine2,
and machine3. The server has a tape drive that is used to do nightly
backups. machine1 is used as a development box and has files that need
to be backed up in /src and in /home. machine2 is used for mail and
needs /home and /mail to be backed up. machine3 is a web server and
needs /home, /var/www, and /etc/httpd backed up.
</p>
<p>
Create a <a href="http://www.rootprompt.org/article.php3?article=8976#rsync-example">shell script</a>
for each machine. Simplify your maintenance by placing the scripts in a
central location. I like to use /root/scripts. Decide on where you want
to log your output. I like <a href="http://www.rootprompt.org/article.php3?article=8976#dir-example">/root/logs</a> but another common option is to have the script <a href="http://www.rootprompt.org/article.php3?article=8976#mail-example">mail</a> you the output.
</p>
<p>
Add entries to your crontab to call the scripts. Make sure you leave
enough time before your normal backups of the server that the rsync
jobs complete.
</p>
<p>
Each night the following will occur:
</p>
<ol>
    <li>rsync machine1 -&gt; Server
    </li>
    <li>rsync machine2 -&gt; Server
    </li>
    <li>rsync machine3 -&gt; Server
    </li>
    <li>backup server to tape
    </li>
</ol>
Let's take a look at the flags used for rsync in the examples:
<p>
rsync -ave ssh --numeric-ids --delete machine1:/home /machine1
</p>
<ul>
    <li>-a:<br />
    Archive mode
    </li>
    <li>-v:<br />
    Verbose output
    </li>
    <li>-e ssh:<br />
    Specify the remote shell as ssh
    </li>
    <li>--numeric-ids:<br />
    Tells rsync to not map user and group id numbers local user and group names
    </li>
    <li>--delete: <br />
    Makes server copy an exact copy of the source by removing any files that have been removed on the remote machine
    </li>
    <li>machine1:/home:<br />
    The remote machine name, then the directory to be backed up
    </li>
    <li>/machine1:<br />
    The directory to place the backup
    </li>
</ul>
<p>Next generate a public private key pair with ssh. Place the public
key in the ~/.ssh/authorized_keys file in an account on machine1,
machine2, and machine3 that has read access to the directories that
need to be backed up. It is best not to use the root account on the
remote machines, but you should evaluate the risk in your environment.
Test that you can login to these accounts using ssh without using a
password.
</p>
<p>Test each one of the rsync scripts. The first time you run
rsync will take the longest as it will need to copy all the files from
the remote machines and not just the files that have changed.
</p>
<p>
Add the /machine1, /machine2, and /machine3 (or whatever you have named them) directories to the servers backup script.
</p>
<p>
While this process does not backup the entire remote machine, it will ensure that you will not lose irreplaceable data.
</p>
<p>Starting with the example scripts included in this tutorial
there are many changes that can be made to fit your specific
circumstances. </p>
<p>
The frequency of the rsyncs can be modified to occur more often or at
different times. Simply by adding additional crontab lines the backup
from the remote machines could be done everyday at lunch, multiple
times a day or even hourly. </p>
<p>
The scripts could also be changed to rotate between multiple backups on
the server or could be changed to do some sort of processing on the
files before they are backed up. For example if the home directories
you are backing up contain web browser caches, they could be removed
after the rsync but before the system backup.
</p>
<p>
Using this article as a starting point you should create a backup plan that fit your needs.
</p>
<p>
</p>
<hr />
<strong><a name="rsync-example">Example rsync script for machine1:</a></strong><hr />
<pre><a name="rsync-example">#!/bin/bash<br />
<br />
rsync -ave ssh --numeric-ids --delete machine1:/home /machine1<br />
rsync -ave ssh --numeric-ids --delete machine1:/src /machine1<br />
<br />
</a></pre>
<hr />
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="rsync-example"></a><strong><a name="rsync-example">Example rsync script for machine2:</a></strong><hr />
<pre><a name="rsync-example">#!/bin/bash<br />
<br />
rsync -ave ssh --numeric-ids --delete machine2:/home /machine2<br />
rsync -ave ssh --numeric-ids --delete machine2:/mail /machine2<br />
<br />
</a></pre>
<hr />
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="rsync-example"></a><strong><a name="rsync-example">Example rsync script for machine3:</a></strong><hr />
<pre><a name="rsync-example">#!/bin/bash<br />
<br />
rsync -ave ssh --numeric-ids --delete machine3:/home /machine3<br />
rsync -ave ssh --numeric-ids --delete machine3:/var/www /machine3<br />
rsync -ave ssh --numeric-ids --delete machine3:/etc/httpd /machine3<br />
<br />
<br />
</a></pre>
<hr />
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="rsync-example"></a><strong><a name="dir-example">Example crontab</a> file logging to a directory:</strong>
<hr />
<pre># Scripts to rsync machines<br />
59 20 * * * /root/scripts/sync-machine1.sh &gt;/root/logs/sync-machine1.log 2&gt;&amp;1<br />
59 21 * * * /root/scripts/sync-machine2.sh &gt;/root/logs/sync-machine2.log 2&gt;&amp;1<br />
59 22 * * * /root/scripts/sync-machine3.sh &gt;/root/logs/sync-machine3.log 2&gt;&amp;1<br />
#<br />
# Nightly Backup script<br />
59 23  * * * /root/scripts/backup.sh &gt; /root/logs/backup.log 2&gt;&amp;1<br />
</pre>
<hr />
<p>
<strong><a name="mail-example">Example crontab</a> file mailing the output:</strong>
</p>
<hr />
<pre># Scripts to rsync machines<br />
59 20 * * * /root/scripts/sync-machine1.sh<br />
59 21 * * * /root/scripts/sync-machine2.sh<br />
59 22 * * * /root/scripts/sync-machine3.sh<br />
#<br />
# Nightly Backup script<br />
59 23  * * * /root/scripts/backup.sh<br />
</pre>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/252067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-01-20 16:29 <a href="http://www.blogjava.net/ruoyoux/articles/252067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PHP Requirements</title><link>http://www.blogjava.net/ruoyoux/articles/251233.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 14 Jan 2009 03:25:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/251233.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/251233.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/251233.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/251233.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/251233.html</trackback:ping><description><![CDATA[<h1 class="title">PHP Requirements</h1>
<p>As PHP version the eZ Components require version <strong>5.2.1</strong>, although a later
version is always recommended. The latest version of PHP can be downloaded
<a class="reference" href="http://php.net/downloads.php">here</a>.</p>
<p>eZ Components versions before the 2008.1 release require PHP version
<strong>5.1.6</strong>. Please be aware that no updates for those releases are being made
anymore.</p>
<p>Some of the components require that certain PHP extensions are enabled in the
build. While most of them are enabled by default, some of them have to
added explicitly. The table below lists all the components, and which
extensions are required or optional.</p>
<div class="section">
<h1><a id="required-and-preferred-extensions" name="required-and-preferred-extensions">Required and Preferred Extensions</a></h1>
<table class="docutils" border="1">
    <colgroup><col width="29%"><col width="20%"><col width="13%"><col width="38%"></colgroup>
    <thead valign="bottom">
        <tr>
            <th class="head">Component</th>
            <th class="head">Extension
            (default)</th>
            <th class="head">Extension
            Required</th>
            <th class="head">Extension
            Optional</th>
        </tr>
    </thead>
    <tbody valign="top">
        <tr>
            <td>All</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#pcre">pcre</a>, <a class="reference" href="http://ezcomponents.org/overview/requirements#spl">spl</a>,
            <a class="reference" href="http://ezcomponents.org/overview/requirements#reflection">reflection</a></td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>Authentication</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#openssl">openssl</a> and <a class="reference" href="http://ezcomponents.org/overview/requirements#bcmath">bcmath</a> or <a class="reference" href="http://ezcomponents.org/overview/requirements#gmp">gmp</a> for
            TypeKey and OpenID support, <a class="reference" href="http://ezcomponents.org/overview/requirements#ldap">ldap</a>
            for LDAP support</td>
        </tr>
        <tr>
            <td>AuthenticationDatabaseTiein</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>Same as <a class="reference" href="http://ezcomponents.org/overview/requirements#database">Database</a></td>
        </tr>
        <tr>
            <td>Archive</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#zlib">zlib</a>, <a class="reference" href="http://ezcomponents.org/overview/requirements#posix">posix</a></td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#bz2">bz2</a></td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#posix">posix</a> for permission support</td>
        </tr>
        <tr>
            <td>Base</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#posix">posix</a></td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#posix">posix</a> to test if features are
            enabled</td>
        </tr>
        <tr>
            <td>Cache</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#memcache">memcache</a> and <a class="reference" href="http://ezcomponents.org/overview/requirements#zlib">zlib</a> for Memcache
            storage, <a class="reference" href="http://ezcomponents.org/overview/requirements#apc">apc</a> for APC storage</td>
        </tr>
        <tr>
            <td>Configuration</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#posix">posix</a></td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>ConsoleTools</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="database">Database</span></td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#pdo">pdo</a>, <a class="reference" href="http://ezcomponents.org/overview/requirements#pdo-sqlite">pdo_sqlite</a></td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#pdo-mysql">pdo_mysql</a>, <a class="reference" href="http://ezcomponents.org/overview/requirements#pdo-oci8">pdo_oci8</a>, <a class="reference" href="http://ezcomponents.org/overview/requirements#pdo-pgsql">pdo_pgsql</a>,
            <a class="reference" href="http://ezcomponents.org/overview/requirements#pdo-mssql">pdo_mssql</a>/<a class="reference" href="http://ezcomponents.org/overview/requirements#pdo-dblib">pdo_dblib</a>, depending on
            the database that you want to use</td>
        </tr>
        <tr>
            <td>DatabaseSchema</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#simplexml">simplexml</a></td>
            <td>&nbsp;</td>
            <td>Same as <a class="reference" href="http://ezcomponents.org/overview/requirements#database">Database</a></td>
        </tr>
        <tr>
            <td>Debug</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>EventLog</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>Same as <a class="reference" href="http://ezcomponents.org/overview/requirements#database">Database</a>, if you want to
            log to a database</td>
        </tr>
        <tr>
            <td>Execution</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>Feed</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#dom">dom</a></td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>File</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>Graph</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#dom">dom</a>, <a class="reference" href="http://ezcomponents.org/overview/requirements#xml">xml</a></td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#gd">gd</a> to generate bitmaps (with
            TrueType font support or Type1 font
            support),
            <a class="reference" href="http://ezcomponents.org/overview/requirements#ming">ming</a> for generating Graphs as flash
            files</td>
        </tr>
        <tr>
            <td>GraphDatabaseTiein</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#pdo">pdo</a></td>
            <td>&nbsp;</td>
            <td>Same as <a class="reference" href="http://ezcomponents.org/overview/requirements#database">Database</a></td>
        </tr>
        <tr>
            <td>ImageAnalysis</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#ctype">ctype</a></td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#exif">exif</a></td>
        </tr>
        <tr>
            <td>ImageConversion</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#gd">gd</a></td>
        </tr>
        <tr>
            <td>Mail</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#iconv">iconv</a></td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#fileinfo">fileinfo</a> for better detection of
            mime-types when sending e-mails,
            <a class="reference" href="http://ezcomponents.org/overview/requirements#mcrypt">mcrypt</a> for NTLM SMTP authentication,
            <a class="reference" href="http://ezcomponents.org/overview/requirements#openssl">openssl</a> for SSL support</td>
        </tr>
        <tr>
            <td>PersistentObject</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>PhpGenerator</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>SignalSlot</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>SystemInformation</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>win32ps (on Windows)</td>
        </tr>
        <tr>
            <td>Template</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>Translation</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#ctype">ctype</a>, <a class="reference" href="http://ezcomponents.org/overview/requirements#simplexml">simplexml</a></td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>TranslationCacheTiein</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>Tree</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#dom">dom</a></td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>TreeDatabaseTiein</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#pdo">pdo</a></td>
            <td>&nbsp;</td>
            <td>Same as <a class="reference" href="http://ezcomponents.org/overview/requirements#database">Database</a></td>
        </tr>
        <tr>
            <td>Url</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>UserInput</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#filter">filter</a></td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>Webdav</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#fileinfo">fileinfo</a> or <a class="reference" href="http://ezcomponents.org/overview/requirements#mimetype">mimetype</a> for detection
            of mime-types of files</td>
        </tr>
        <tr>
            <td>Workflow</td>
            <td><a class="reference" href="http://ezcomponents.org/overview/requirements#simplexml">simplexml</a>, <a class="reference" href="http://ezcomponents.org/overview/requirements#dom">dom</a></td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>WorkflowDatabaseTiein</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>Same as <a class="reference" href="http://ezcomponents.org/overview/requirements#database">Database</a></td>
        </tr>
        <tr>
            <td>WorkflowEventLogTiein</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>Same as <a class="reference" href="http://ezcomponents.org/overview/requirements#database">Database</a>, if you want to
            log to a database</td>
        </tr>
    </tbody>
</table>
</div>
<h1><a id="quick-reference-on-enabling-extensions" name="quick-reference-on-enabling-extensions">Quick Reference on Enabling Extensions</a></h1>
<div class="section">
<h2><a id="extensions-that-are-enabled-by-default-in-php" name="extensions-that-are-enabled-by-default-in-php">Extensions that are enabled by default in PHP</a></h2>
<table class="docutils" border="1">
    <colgroup><col width="32%"><col width="68%"></colgroup>
    <thead valign="bottom">
        <tr>
            <th class="head">Extension</th>
            <th class="head">Configure switch(es)</th>
        </tr>
    </thead>
    <tbody valign="top">
        <tr>
            <td><span class="target" id="ctype">ctype</span></td>
            <td>--enable-ctype</td>
        </tr>
        <tr>
            <td><span class="target" id="dom">dom</span></td>
            <td>--enable-dom --enable-libxml</td>
        </tr>
        <tr>
            <td><span class="target" id="iconv">iconv</span></td>
            <td>--with-iconv</td>
        </tr>
        <tr>
            <td><span class="target" id="pcre">pcre</span></td>
            <td>--with-pcre-regex</td>
        </tr>
        <tr>
            <td><span class="target" id="pdo">pdo</span></td>
            <td>--enable-pdo</td>
        </tr>
        <tr>
            <td><span class="target" id="pdo-sqlite">pdo_sqlite</span></td>
            <td>--with-pdo-sqlite</td>
        </tr>
        <tr>
            <td><span class="target" id="posix">posix</span></td>
            <td>--enable-posix</td>
        </tr>
        <tr>
            <td><span class="target" id="reflection">reflection</span></td>
            <td>--enable-reflection</td>
        </tr>
        <tr>
            <td><span class="target" id="simplexml">simplexml</span></td>
            <td>--enable-simplexml</td>
        </tr>
        <tr>
            <td><span class="target" id="spl">spl</span></td>
            <td>--enable-spl</td>
        </tr>
        <tr>
            <td><span class="target" id="xml">xml</span></td>
            <td>--enable-xml</td>
        </tr>
        <tr>
            <td><span class="target" id="zlib">zlib</span></td>
            <td>--with-zlib</td>
        </tr>
    </tbody>
</table>
</div>
<div class="section">
<h2><a id="extensions-that-are-bundled-with-php" name="extensions-that-are-bundled-with-php">Extensions that are bundled with PHP</a></h2>
<table class="docutils" border="1">
    <colgroup><col width="15%"><col width="38%"><col width="47%"></colgroup>
    <thead valign="bottom">
        <tr>
            <th class="head">Extension</th>
            <th class="head">Configure switch(es)</th>
            <th class="head">Remarks</th>
        </tr>
    </thead>
    <tbody valign="top">
        <tr>
            <td><span class="target" id="bcmath">bcmath</span></td>
            <td>--enable-bcmath</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="bz2">bz2</span></td>
            <td>--with-bz2</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="gd">gd</span></td>
            <td>--with-gd --with-freetype-dir=/usr
            --with-jpeg-dir=/usr --with-ttf
            --with-xpm-dir --with-png-dir
            --with-jpeg-dir --with-t1lib</td>
            <td>The eZ Components want at least
            PNG and JPG support, other
            parts are optional.  We
            suggest to compile GD also
            with FreeType2 support as
            well to enable all features
            of the Components.</td>
        </tr>
        <tr>
            <td><span class="target" id="gmp">gmp</span></td>
            <td>--with-gmp</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="ldap">ldap</span></td>
            <td>--with-ldap</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="mcrypt">mcrypt</span></td>
            <td>--with-mcrypt</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="mimetype">mimetype</span></td>
            <td>--with-mime-magic</td>
            <td>Deprecated in favour of <a class="reference" href="http://ezcomponents.org/overview/requirements#fileinfo">fileinfo</a>.</td>
        </tr>
        <tr>
            <td><span class="target" id="ming">ming</span></td>
            <td>--with-ming</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="exif">exif</span></td>
            <td>--enable-exif</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="filter">filter</span></td>
            <td>--enable-filter</td>
            <td>In PHP 5.2.0 and higher you can simply
            use --enable-filter, in PHP 5.1.x you
            need to install the <a class="reference" href="http://pecl.php.net/package/filter">filter extension</a>
            through PECL.</td>
        </tr>
        <tr>
            <td><span class="target" id="pdo-mysql">pdo_mysql</span></td>
            <td>--with-pdo-mysql</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="pdo-oci8">pdo_oci8</span></td>
            <td>--with-pdo-oci</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="pdo-pgsql">pdo_pgsql</span></td>
            <td>--with-pdo-pgsql</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td><span class="target" id="pdo-mssql">pdo_mssql</span></td>
            <td>--with-pdo-mssql</td>
            <td>On Windows (on Linux use <a class="reference" href="http://ezcomponents.org/overview/requirements#pdo-dblib">pdo_dblib</a>)</td>
        </tr>
        <tr>
            <td><span class="target" id="pdo-dblib">pdo_dblib</span></td>
            <td>--with-pdo-dblib</td>
            <td>Mssql driver for Linux (on Windows use
            <a class="reference" href="http://ezcomponents.org/overview/requirements#pdo-mssql">pdo_mssql</a>). The FreeTDS software must be
            installed also.</td>
        </tr>
        <tr>
            <td><span class="target" id="openssl">openssl</span></td>
            <td>--with-openssl</td>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<h2><a id="extensions-that-are-not-bundled-with-php" name="extensions-that-are-not-bundled-with-php">Extensions that are not bundled with PHP</a></h2>
<table class="docutils" border="1">
    <colgroup><col width="14%"><col width="86%"></colgroup>
    <thead valign="bottom">
        <tr>
            <th class="head">Extension</th>
            <th class="head">Configure switch(es)</th>
        </tr>
    </thead>
    <tbody valign="top">
        <tr>
            <td><span class="target" id="apc">apc</span></td>
            <td>You need to install the <a class="reference" href="http://pecl.php.net/package/apc">APC extension</a> through PECL.</td>
        </tr>
        <tr>
            <td><span class="target" id="fileinfo">fileinfo</span></td>
            <td>
            <p class="first">You need to install the <a class="reference" href="http://pecl.php.net/package/fileinfo">fileinfo extension</a> through PECL.</p>
            <dl class="last docutils"><dt>On Windows additional configuration steps are required:</dt><dd>
            <ul class="first last">
                <li>
                <p class="first">download <tt class="docutils literal"><span class="pre">magic</span></tt> and <tt class="docutils literal"><span class="pre">magic.mime</span></tt> files from <a class="reference" href="http://gnuwin32.sourceforge.net/packages/file.htm">gnuwin32</a> (from the
                Binaries Zip in the File for Windows package) and copy them to a folder,
                for example the folder where PHP is installed (e.g. <tt class="docutils literal"><span class="pre">c:\php</span></tt>)</p>
                </li>
                <li>
                <p class="first">in System settings, setup the enviroment variable <strong>MAGIC</strong> to point
                to the folder where you copied the magic files, plus the <tt class="docutils literal"><span class="pre">magic</span></tt>
                part (e.g. <tt class="docutils literal"><span class="pre">c:\php\magic</span></tt>). Restart Windows if needed.</p>
                </li>
                <li>
                <p class="first">alternatively you can use this command-line before running your PHP
                scripts:</p>
                <pre class="literal-block">set MAGIC=c:\php\magic<br />
                </pre>
                </li>
            </ul>
            </dd></dl></td>
        </tr>
        <tr>
            <td><span class="target" id="memcache">memcache</span></td>
            <td>You need to install the <a class="reference" href="http://pecl.php.net/package/memcache">Memcache extension</a> through PECL.</td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/251233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-01-14 11:25 <a href="http://www.blogjava.net/ruoyoux/articles/251233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Ubuntu/Debian包管理命令大全（apt &amp; dpkg）</title><link>http://www.blogjava.net/ruoyoux/articles/250647.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Fri, 09 Jan 2009 03:57:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/250647.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/250647.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/250647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/250647.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/250647.html</trackback:ping><description><![CDATA[<p class="g_w_100 g_t_wrap g_t_center g_t_bold g_t_24 g_c_pdin c07" id="blogtitle_fks_085065087081085067085082085095092095085065087081086">[转载]Ubuntu/Debian包管理命令大全（apt &amp; dpkg）</p>
apt-cache search # ------(package 搜索包)<br />
apt-cache show #------(package 获取包的相关信息，如说明、大小、版本等)<br />
apt-get install # ------(package 安装包)<br />
apt-get install # -----(package --reinstall 重新安装包)<br />
apt-get -f install # -----(强制安装, "-f = --fix-missing"当是修复安装吧...)<br />
apt-get remove #-----(package 删除包)<br />
apt-get remove --purge # ------(package 删除包，包括删除配置文件等)<br />
apt-get autoremove --purge # ----(package 删除包及其依赖的软件包+配置文件等（只对6.10有效，强烈推荐）)<br />
apt-get update #------更新源<br />
apt-get upgrade #------更新已安装的包<br />
apt-get dist-upgrade # ---------升级系统<br />
apt-get dselect-upgrade #------使用 dselect 升级<br />
apt-cache depends #-------(package 了解使用依赖)<br />
apt-cache rdepends # ------(package 了解某个具体的依赖,当是查看该包被哪些包依赖吧...)<br />
apt-get build-dep # ------(package 安装相关的编译环境)<br />
apt-get source #------(package 下载该包的源代码)<br />
apt-get clean &amp;&amp; apt-get autoclean # --------清理下载文件的存档 &amp;&amp; 只清理过时的包<br />
apt-get check #-------检查是否有损坏的依赖<br />
dpkg -S filename -----查找filename属于哪个软件包<br />
apt-file search filename -----查找filename属于哪个软件包<br />
apt-file list packagename -----列出软件包的内容<br />
apt-file update --更新apt-file的数据库<br />
<br />
dpkg --info "软件包名" --列出软件包解包后的包名称.<br />
dpkg -l --列出当前系统中所有的包.可以和参数less一起使用在分屏查看. (类似于rpm -qa)<br />
dpkg -l |grep -i "软件包名" --查看系统中与"软件包名"相关联的包.<br />
dpkg -s 查询已安装的包的详细信息.<br />
dpkg -L 查询系统中已安装的软件包所安装的位置. (类似于rpm -ql)<br />
dpkg -S 查询系统中某个文件属于哪个软件包. (类似于rpm -qf)<br />
dpkg -I 查询deb包的详细信息,在一个软件包下载到本地之后看看用不用安装(看一下呗).<br />
dpkg -i 手动安装软件包(这个命令并不能解决软件包之前的依赖性问题),如果在安装某一个软件包的时候遇到了软件依赖的问题,可以用apt-get -f install在解决信赖性这个问题.<br />
dpkg -r 卸载软件包.不是完全的卸载,它的配置文件还存在.<br />
dpkg -P 全部卸载(但是还是不能解决软件包的依赖性的问题)<br />
dpkg -reconfigure 重新配置<br />
<br />
<br />
apt-get install<br />
下载软件包，以及所有依赖的包，同时进行包的安装或升级。如果某个包被设置了 hold (停止标志，就会被搁在一边(即不会被升级)。更多 hold 细节请看下面。<br />
apt-get remove [--purge]<br />
移除 以及任何依赖这个包的其它包。<br />
--purge 指明这个包应该被完全清除 (purged) ，更多信息请看 dpkg -P。<br />
<br />
apt-get update<br />
升级来自 Debian 镜像的包列表，如果你想安装当天的任何软件，至少每天运行一次，而且每次修改了<br />
/etc/apt/sources.list 後，必须执行。<br />
<br />
apt-get upgrade [-u]<br />
升
级所有已经安装的包为最新可用版本。不会安装新的或移除老的包。如果一个包改变了依赖关系而需要安装一个新的包，那么它将不会被升级，而是标志为
hold。apt-get update 不会升级被标志为 hold 的包 (这个也就是 hold 的意思)。请看下文如何手动设置包为
hold。我建议同时使用 '-u' 选项，因为这样你就能看到哪些包将会被升级。<br />
<br />
apt-get dist-upgrade [-u]<br />
和 apt-get upgrade 类似，除了 dist-upgrade 会安装和移除包来满足依赖关系。因此具有一定的危险性。<br />
<br />
apt-cache search<br />
在软件包名称和描述中，搜索包含xxx的软件包。<br />
<br />
apt-cache show<br />
显示某个软件包的完整的描述。<br />
<br />
apt-cache showpkg<br />
显示软件包更多细节，以及和其它包的关系。<br />
<br />
dselect<br />
console-apt<br />
aptitude<br />
gnome-apt<br />
APT 的几个图形前端(其中一些在使用前得先安装)。这里 dselect 无疑是最强大的，也是最古老，最难驾驭。<br />
<br />
普通 Dpkg 用法<br />
dpkg -i<br />
安装一个 Debian 包文件，如你手动下载的文件。<br />
<br />
dpkg -c<br />
列出 的内容。<br />
<br />
dpkg -I<br />
从 中提取包信息。<br />
<br />
dpkg -r<br />
移除一个已安装的包。<br />
<br />
dpkg -P<br />
完全清除一个已安装的包。和 remove 不同的是，remove 只是删掉数据和可执行文件，purge 另外还删除所有的配制文件。<br />
<br />
dpkg -L<br />
列出 安装的所有文件清单。同时请看 dpkg -c 来检查一个 .deb 文件的内容。<br />
<br />
dpkg -s<br />
显示已安装包的信息。同时请看 apt-cache 显示 Debian 存档中的包信息，以及 dpkg -I 来显示从一个 .deb 文件中提取的包信息。<br />
<br />
dpkg-reconfigure<br />
重
新配制一个已经安装的包，如果它使用的是 debconf (debconf 为包安装提供了一个统一的配制界面)。你能够重新配制 debconf
它本身，如你想改变它的前端或提问的优先权。例如，重新配制 debconf，使用一个 dialog 前端，简单运行：<br />
<br />
dpkg-reconfigure --frontend=dialog debconf (如果你安装时选错了，这里可以改回来哟：)<br />
<br />
echo " hold" | dpkg --set-selections<br />
设置 的状态为 hlod (命令行方式)<br />
<br />
dpkg --get-selections ""<br />
取的 的当前状态 (命令行方式)<br />
<br />
支持通配符，如：<br />
Debian:~# dpkg --get-selections *wine*<br />
libwine hold<br />
libwine-alsa hold<br />
libwine-arts hold<br />
libwine-dev hold<br />
libwine-nas hold<br />
libwine-print hold<br />
libwine-twain hold<br />
wine hold<br />
wine+ hold<br />
wine-doc hold<br />
wine-utils hold<br />
<br />
例如：<br />
大家现在用的都是 gaim-0.58 + QQ-plugin，为了防止 gaim 被升级，我们可以采用如下方法：<br />
<br />
方法一：<br />
Debian:~# echo "gaim hold" | dpkg --set-selections<br />
然後用下面命令检查一下：<br />
Debian:~# dpkg --get-selections "gaim"<br />
gaim hold<br />
现在的状态标志是 hold，就不能被升级了。<br />
<br />
如果想恢复怎么办呢?<br />
Debian:~# echo "gaim install" | dpkg --set-selections<br />
Debian:~# dpkg --get-selections "gaim"<br />
gaim install<br />
这时状态标志又被重置为 install，可以继续升级了。<br />
<br />
同志们会问，哪个这些状态标志都写在哪个文件中呢?<br />
在 /var/lib/dpkg/status 里，你也可以通过修改这个文件实现 hold。<br />
<br />
有时你会发现有的软件状态标志是 purge，不要奇怪。<br />
如：事先已经安装了 amsn，然後把它卸了。<br />
apt-get remove --purge amsn<br />
那么状态标志就从 install 变成 purge。<br />
<br />
方法二：<br />
在/etc/apt 下手动建一个 preferences 文件<br />
内容：<br />
Package: gaim<br />
Pin: version 0.58*<br />
保存<br />
<br />
dpkg -S<br />
在包数据库中查找 ，并告诉你哪个包包含了这个文件。(注：查找的是事先已经安装的包)<br />
<br />
--------------------------------------------<br />
Debian的软件包管理工具命令不完全列表<br />
--------------------------------------------<br />
Debian系统中所有的包信息都在/var/lib/dpkg下.其中/var/lib/dpkg/info目录中保存了各个软件包的信息及管理文件.每个文件的作用如下:<br />
&nbsp;以&nbsp; ".conffiles"&nbsp;&nbsp;&nbsp;&nbsp; 结尾的文件记录软件包的配置列表.<br />
&nbsp;以&nbsp; ".list"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 结尾的文件记录了软件包的文件列表,用户可在文件当中找到软件包文件的具体安装位置.<br />
&nbsp;以&nbsp; ".md5sums"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 结尾的文件记录了md5信息,用来进行包的验证的.<br />
&nbsp;以&nbsp; ".config"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 结尾的文件是软件包的安装配置角本.<br />
&nbsp;以&nbsp; ".postinst"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 角本是完成Debian包解开之后的配置工作,通常用来执行所安装软件包相关的命令和服务的重新启动.<br />
&nbsp;以&nbsp; ".preinst"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 角本在Debain解包之前运行,主要作用是是停止作用于即将升级的软件包服务直到软件包安装或和升级完成.<br />
&nbsp;以&nbsp; ".prerm"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 脚本负责停止与软件包关联的daemon服务,在删除软件包关联文件之前执行.<br />
&nbsp;以&nbsp; ".postrm"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 脚本负责修改软件包链接或文件关联,或删除由它创建的文件.<br />
&nbsp;<br />
&nbsp;/var/lib/dpkg/available是软件包的描述信息.<br />
&nbsp;包括当前系统中所有使用的Debian安装源中所有的软件包,还包括当前系统中已经安装和未安装的软件包.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
1.dpkg包管理工具<br />
&nbsp; dpkg --info "软件包名" --列出软件包解包后的包名称.<br />
&nbsp; dpkg -l&nbsp;&nbsp;&nbsp;&nbsp; --列出当前系统中所有的包.可以和参数less一起使用在分屏查看.<br />
&nbsp; dpkg -l |grep -i "软件包名" --查看系统中与"软件包名"相关联的包.<br />
&nbsp; dpkg -s&nbsp;&nbsp; 查询已安装的包的详细信息.<br />
&nbsp; dpkg -L&nbsp;&nbsp; 查询系统中已安装的软件包所安装的位置.<br />
&nbsp; dpkg -S&nbsp;&nbsp; 查询系统中某个文件属于哪个软件包.<br />
&nbsp; dpkg -I&nbsp;&nbsp; 查询deb包的详细信息,在一个软件包下载到本地之后看看用不用安装(看一下呗).<br />
&nbsp; dpkg -i 手动安装软件包(这个命令并不能解决软件包之前的依赖性问题),如果在安装某一个软件包的时候遇到了软件依赖的问题,可以用apt-get -f install在解决信赖性这个问题.<br />
&nbsp; dpkg -r 卸载软件包.不是完全的卸载,它的配置文件还存在.<br />
&nbsp; dpkg -P 全部卸载(但是还是不能解决软件包的依赖性的问题)<br />
&nbsp; dpkg -reconfigure 重新配置<br />
2. apt高级包管理工具<br />
&nbsp;&nbsp; (1)GTK图形的"synaptic",这是APT的前端工具.<br />
&nbsp;&nbsp; (2)"aptitude",这也是APT的前端工具.<br />
&nbsp;&nbsp; 用APT管理工具进行包的管理,可以有以下几种方法做源:<br />
&nbsp;&nbsp; (1)拿安装盘做源,方法如下:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; apt-cdrom ident&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 扫描光盘的信息<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; apt-cdrom add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 添加光盘源<br />
&nbsp;&nbsp; (2)这也是最常用的方法就是把源添加到/etc/apt/source.list中,之后更新列apt-get&nbsp; update<br />
&nbsp; APT管理工具常用命令<br />
&nbsp; apt-cache 加上不同的子命令和参数的使用可以实现查找,显示软件,包信息及包信赖关系等功能.<br />
&nbsp; apt-cache stats 显示当前系统所有使用的Debain数据源的统计信息.<br />
&nbsp; apt-cache search +"包名",可以查找相关的软件包.<br />
&nbsp; apt-cache show&nbsp;&nbsp; +"包名",可以显示指定软件包的详细信息.<br />
&nbsp; apt-cache depends +"包名",可以查找软件包的依赖关系.<br />
&nbsp; apt-get upgrade&nbsp;&nbsp; 更新系统中所有的包到最新版<br />
&nbsp; apt-get install&nbsp;&nbsp; 安装软件包<br />
&nbsp; apt-get --reindtall install 重新安装软件包<br />
&nbsp; apt-get remove 卸载软件包<br />
&nbsp; apt-get --purge remove 完全卸载软件包<br />
&nbsp; apt-get clean 清除无用的软件包<br />
&nbsp; 在用命令apt-get install之前,是先将软件包下载到/var/cache/apt/archives中,之后再进行安装的.所以我们可以用apt-get clean清除/var/cache/apt/archives目录中的软件包.<br />
&nbsp; 源码包安装<br />
&nbsp;&nbsp; apt-cache showsrc 查找看源码包的文件信息(在下载之前)<br />
&nbsp;&nbsp; apt-get source 下载源码包.<br />
&nbsp;&nbsp; apt-get build-dep +"包名" 构建源码包的编译环境.<br />
<img src ="http://www.blogjava.net/ruoyoux/aggbug/250647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-01-09 11:57 <a href="http://www.blogjava.net/ruoyoux/articles/250647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux_Users_and_Sudo</title><link>http://www.blogjava.net/ruoyoux/articles/241458.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 19 Nov 2008 11:18:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/241458.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/241458.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/241458.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/241458.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/241458.html</trackback:ping><description><![CDATA[<h1> <span class="mw-headline">Introduction</span></h1>
<p>Before we proceed, it would be best to cover some basic user administration topics that will be very useful in later chapters.
Adding Users
</p>
<p>One of the most important activities in administering a Linux
box is the addition of users. Here you'll find some simple examples to
provide a foundation for future chapters. It is not intended to be
comprehensive, but is a good memory refresher. You can use the command
man useradd to get the help pages on adding users with the useradd
command or the man usermod to become more familiar with modifying users
with the usermod command.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Who_Is_the_Super_User.3F"></a>
<h1> <span class="mw-headline"> Who Is the Super User? </span></h1>
<p>The super user with unrestricted access to all system resources and
files in Linux is the user named root. This user has a user ID, of 0
which is universally identified by Linux applications as belonging to a
user with supreme privileges. You will need to log in as user root to
add new users to your Linux server.
</p>
<p><strong>Debian Note:</strong> When installing Ubuntu Linux systems, you are prompted to create a primary user that is not <code>root</code>. A <code>root</code>
user is created but no password is set, so you initially cannot log in
as this user. The primary user can become the root user using the <code>sudo su -</code> command that will be discussed later.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="How_To_Add_Users"></a>
<h1> <span class="mw-headline"> How To Add Users </span></h1>
<p>Adding users takes some planning; read through these steps below before starting:
</p>
<p>1) Arrange your list of users into groups by function. In this example there are three groups "parents", "children" and "soho".
</p>
<pre>Parents    Children    Soho<br />
<br />
Paul       Alice       Accounts<br />
Jane       Derek       Sales<br />
</pre>
<p>2) Add the Linux groups to your server:
</p>
<pre>[root@bigboy tmp]# groupadd parents<br />
[root@bigboy tmp]# groupadd children<br />
[root@bigboy tmp]# groupadd soho<br />
</pre>
<p>3) Add the Linux users and assign them to their respective groups
</p>
<pre>[root@bigboy tmp]# useradd -g parents paul<br />
[root@bigboy tmp]# useradd -g parents jane<br />
[root@bigboy tmp]# useradd -g children derek<br />
[root@bigboy tmp]# useradd -g children alice<br />
[root@bigboy tmp]# useradd -g soho accounts<br />
[root@bigboy tmp]# useradd -g soho sales<br />
</pre>
<p>If you don't specify the group with the -g, RedHat/Fedora Linux
creates a group with the same name as the user you just created; this
is also known as the User Private Group Scheme. When each new user
first logs in, they are prompted for their new permanent password.
</p>
<p>4) Each user's personal directory is placed in the /home directory. The directory name will be the same as their user name.
</p>
<pre> [root@bigboy tmp]# ll /home<br />
drwxr-xr-x    2 root     root        12288 Jul 24 20:04 lost+found<br />
drwx------    2 accounts soho         1024 Jul 24 20:33 accounts<br />
drwx------    2 alice    children     1024 Jul 24 20:33 alice<br />
drwx------    2 derek    children     1024 Jul 24 20:33 derek<br />
drwx------    2 jane     parents      1024 Jul 24 20:33 jane<br />
drwx------    2 paul     parents      1024 Jul 24 20:33 paul<br />
drwx------    2 sales    soho         1024 Jul 24 20:33 sales<br />
[root@bigboy tmp]#<br />
</pre>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="How_to_Change_Passwords"></a>
<h1> <span class="mw-headline"> How to Change Passwords </span></h1>
<p>You need to create passwords for each account. This is done with the
passwd command. You are prompted once for your old password and twice
for the new one.
</p>
<ul>
    <li> User root changing the password for user paul.
    </li>
</ul>
<pre>[root@bigboy root]# passwd paul<br />
Changing password for user paul.<br />
New password: <br />
Retype new password: <br />
passwd: all authentication tokens updated successfully.<br />
[root@bigboy root]#<br />
</pre>
<ul>
    <li> Users might wish to change their passwords at a future date. Here is how unprivileged user paul would change his own password.
    </li>
</ul>
<pre>[paul@bigboy paul]$ passwd<br />
Changing password for paul<br />
Old password: your current password<br />
Enter the new password (minimum of 5, maximum of 8 characters)<br />
Please use a combination of upper and lower case letters and numbers.<br />
New password: your new password<br />
Re-enter new password: your new password<br />
Password changed.<br />
[paul@bigboy paul]$<br />
</pre>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="How_to_Delete_Users"></a>
<h2> <span class="mw-headline"> How to Delete Users </span></h2>
<p>The userdel command is used to remove the user's record from the
/etc/passwd and /etc/shadow used in the login process. The command has
a single argument, the username.
</p>
<pre>[root@bigboy tmp]# userdel paul<br />
</pre>
<p>There is also an optional -r switch that additionally removes all
the contents of the user's home directory. Use this option with care.
The data in a user's directory can often be important even after the
person has left your company.
</p>
<pre>[root@bigboy tmp]# userdel -r paul<br />
</pre>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="How_to_Tell_the_Groups_to_Which_a_User_Belongs"></a>
<h2> <span class="mw-headline"> How to Tell the Groups to Which a User Belongs </span></h2>
<p>Use the groups command with the username as the argument.
</p>
<pre>[root@bigboy root]# groups paul<br />
paul&nbsp;: parents<br />
[root@bigboy root]#<br />
</pre>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="How_to_Change_the_Ownership_of_a_File"></a>
<h2> <span class="mw-headline"> How to Change the Ownership of a File </span></h2>
<p>You can change the ownership of a file with the chown command. The
first argument is the desired username and group ownership for the file
separated by a colon (:) followed by the filename. In the next example
we change the ownership of the file named text.txt from being owned by
user root and group root to being owned by user testuser in the group
users:
</p>
<pre>[root@bigboy tmp]# ll test.txt<br />
-rw-r--r--  1 root root 0 Nov 17 22:14 test.txt<br />
[root@bigboy tmp]# chown testuser:users test.txt<br />
[root@bigboy tmp]# ll test.txt<br />
-rw-r--r--  1 testuser users 0 Nov 17 22:14 test.txt<br />
[root@bigboy tmp]#<br />
</pre>
<p>You can also use the chown command with the -r switch for it to doe
recursive searches down into directories to change permissions.
</p>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Using_sudo"></a>
<h1> <span class="mw-headline"> Using sudo </span></h1>
<p>If a server needs to be administered by a number of people it is
normally not a good idea for them all to use the root account. This is
because it becomes difficult to determine exactly who did what, when
and where if everyone logs in with the same credentials. The sudo
utility was designed to overcome this difficulty.
</p>
<p>The sudo utility allows users defined in the /etc/sudoers
configuration file to have temporary access to run commands they would
not normally be able to due to file permission restrictions. The
commands can be run as user "root" or as any other user defined in the
/etc/sudoers configuration file.
</p>
<p>The privileged command you want to run must first begin with
the word sudo followed by the command's regular syntax. When running
the command with the sudo prefix, you will be prompted for your regular
password before it is executed. You may run other privileged commands
using sudo within a five-minute period without being re-prompted for a
password. All commands run as sudo are logged in the log file
/var/log/messages.
</p>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Simple_Sudo_Examples"></a>
<h2> <span class="mw-headline">Simple Sudo Examples</span></h2>
<p>Using sudo is relatively simple as we can see from these examples.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Temporarily_Gaining_root_Privileges"></a>
<h3> <span class="mw-headline"> Temporarily Gaining root Privileges </span></h3>
<p>In this example, user bob attempts to view the contents of the
/etc/sudoers file, which is an action that normally requires privileged
access. Without sudo, the command fails:
</p>
<pre>[bob@bigboy bob]$ more /etc/sudoers<br />
/etc/sudoers: Permission denied<br />
[bob@bigboy bob]$<br />
</pre>
<p>Bob tries again using sudo and his regular user password and is successful:
</p>
<pre>[bob@bigboy bob]$ sudo more /etc/sudoers<br />
Password:<br />
...<br />
...<br />
[bob@bigboy bob]$<br />
</pre>
<p>The details of configuring and installing sudo are covered in later sections.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Becoming_root_for_a_Complete_Login_Session"></a>
<h3> <span class="mw-headline"> Becoming root for a Complete Login Session </span></h3>
<p>The <code>su</code> command allows a regular user to become the system's <code>root</code> user if they know the <code>root</code> password. A user with <code>sudo</code> rights to use the <code>su</code> command can become <code>root</code>, but they only need to know their own password, not that of <code>root</code> as seen here.
</p>
<pre>someuser@u-bigboy:~$ sudo su -<br />
Password:<br />
root@u-bigboy:~#<br />
</pre>
<p>Some systems administrators will use <code>sudo</code> to grant <code>root</code> privileges to their own personal user account without the need to provide a password.
</p>
<p>Later sections describe how to disable <code>sudo su</code> ability and also how to use <code>sudo</code> without password prompts.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Downloading_and_Installing_the_sudo_Package"></a>
<h2> <span class="mw-headline"> Downloading and Installing the sudo Package </span></h2>
<p>Fortunately the package is installed by default by RedHat/Fedora which eliminates the need to anything more in this regard.
The visudo Command
</p>
<p>The visudo command is a text editor that mimics the vi editor
that is used to edit the /etc/sudoers configuration file. It is not
recommended that you use any other editor to modify your sudo
parameters because the sudoers file isn't located in the same directory
on all versions of Linux. visudo uses the same commands as the vi text
editor. The visudo command must run as user root and should have no
arguments:
</p>
<pre>[root@aqua tmp]# visudo<br />
</pre>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="The_.2Fetc.2Fsudoers_File"></a>
<h2> <span class="mw-headline"> The /etc/sudoers File </span></h2>
<p>The /etc/sudoers file contains all the configuration and permission
parameters needed for sudo to work. There are a number of guidelines
that need to be followed when editing it with visudo.
General /etc/sudoers Guidelines
</p>
<p>The /etc/sudoers file has the general format shown in Table 9-1.
</p>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Table_9-1_Format_of_the_.2Fetc.2Fsudoers_File"></a>
<h3> <span class="mw-headline"> Table 9-1 Format of the /etc/sudoers File </span></h3>
<div align="center">
<table class="MsoTableGrid" style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="padding: 0.05in; background: green none repeat scroll 0% 50%; width: 6.15in; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="738">
            <p class="MsoNormal" style="text-align: center;" align="center"><strong><span style="color: white;">General sudoers File Record Format</span></strong></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0.05in; width: 6.15in;" valign="top" width="738">
            <p class="MsoNormal" style="text-align: center;" align="center"><tt><strong>usernames/group&nbsp;servername
            = (usernames command can be run as) command</strong></tt></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>There are some general guidelines when editing this file:
</p>
<ul>
    <li> Groups are the same as user groups and are differentiated from
    regular users by a&nbsp;% at the beginning. The Linux user group "users"
    would be represented by&nbsp;%users.
    </li>
    <li> You can have multiple usernames per line separated by commas.
    </li>
    <li> Multiple commands also can be separated by commas. Spaces are considered part of the command.
    </li>
    <li> The keyword ALL can mean all usernames, groups, commands and servers.
    </li>
    <li> If you run out of space on a line, you can end it with a back slash (\) and continue on the next line.
    </li>
    <li> sudo assumes that the sudoers file will be used network wide,
    and therefore offers the option to specify the names of servers which
    will be using it in the servername position in Table 9-1. In most
    cases, the file is used by only one server and the keyword ALL suffices
    for the server name.
    </li>
    <li> The NOPASSWD keyword provides access without prompting for your password.
    </li>
</ul>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Simple_.2Fetc.2Fsudoers_Examples"></a>
<h2> <span class="mw-headline"> Simple /etc/sudoers Examples </span></h2>
<p>This section presents some simple examples of how to do many commonly required tasks using the sudo utility.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Granting_All_Access_to_Specific_Users"></a>
<h3> <span class="mw-headline"> Granting All Access to Specific Users </span></h3>
<p>You can grant users bob and bunny full access to all privileged commands, with this sudoers entry.
</p>
<pre>bob, bunny  ALL=(ALL) ALL<br />
</pre>
<p>This is generally not a good idea because this allows bob and bunny
to use the su command to grant themselves permanent root privileges
thereby bypassing the command logging features of sudo. The example on
using aliases in the sudoers file shows how to eliminate this prob
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Granting_Access_To_Specific_Users_To_Specific_Files"></a>
<h3> <span class="mw-headline"> Granting Access To Specific Users To Specific Files </span></h3>
<p>This entry allows user peter and all the members of the group
operator to gain access to all the program files in the /sbin and
/usr/sbin directories, plus the privilege of running the command
/usr/local/apps/check.pl. Notice how the trailing slash (/) is required
to specify a directory location:
</p>
<pre>peter,&nbsp;%operator ALL= /sbin/, /usr/sbin, /usr/local/apps/check.pl<br />
</pre>
<p>Notice also that the lack of any username entries within parentheses
() after the = sign prevents the users from running the commands
automatically masquerading as another user. This is explained further
in the next example.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Granting_Access_to_Specific_Files_as_Another_User"></a>
<h3> <span class="mw-headline"> Granting Access to Specific Files as Another User </span></h3>
<p>The sudo -u entry allows allows you to execute a command as if you
were another user, but first you have to be granted this privilege in
the sudoers file.
</p>
<p>This feature can be convenient for programmers who sometimes
need to kill processes related to projects they are working on. For
example, programmer peter is on the team developing a financial package
that runs a program called monthend as user accounts. From time to time
the application fails, requiring "peter" to stop it with the /bin/kill,
/usr/bin/kill or /usr/bin/pkill commands but only as user "accounts".
The sudoers entry would look like this:
</p>
<pre>peter ALL=(accounts) /bin/kill, /usr/bin/kill, /usr/bin/pkill<br />
</pre>
<p>User peter is allowed to stop the monthend process with this command:
</p>
<pre>[peter@bigboy peter]# sudo -u accounts pkill monthend<br />
</pre>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Granting_Access_Without_Needing_Passwords"></a>
<h3> <span class="mw-headline"> Granting Access Without Needing Passwords </span></h3>
<p>This example allows all users in the group operator to execute all
the commands in the /sbin directory without the need for entering a
password. This has the added advantage of being more convenient to the
user:
</p>
<pre>%operator ALL= NOPASSWD: /sbin/<br />
</pre>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Using_Aliases_in_the_sudoers_File"></a>
<h3> <span class="mw-headline"> Using Aliases in the sudoers File </span></h3>
<p>Sometimes you'll need to assign random groupings of users from
various departments very similar sets of privileges. The sudoers file
allows users to be grouped according to function with the group and
then being assigned a nickname or alias which is used throughout the
rest of the file. Groupings of commands can also be assigned aliases
too.
</p>
<p>In the next example, users peter, bob and bunny and all the
users in the operator group are made part of the user alias ADMINS. All
the command shell programs are then assigned to the command alias
SHELLS. Users ADMINS are then denied the option of running any SHELLS
commands and su:
</p>
<pre>Cmnd_Alias    SHELLS = /usr/bin/sh,  /usr/bin/csh, \<br />
/usr/bin/ksh, /usr/local/bin/tcsh, \<br />
/usr/bin/rsh, /usr/local/bin/zsh<br />
<br />
<br />
User_Alias    ADMINS = peter, bob, bunny,&nbsp;%operator<br />
ADMINS        ALL    =&nbsp;!/usr/bin/su,&nbsp;!SHELLS<br />
</pre>
<p>This attempts to ensure that users don't permanently su to become
root, or enter command shells that bypass sudo's command logging. It
doesn't prevent them from copying the files to other locations to be
run. The advantage of this is that it helps to create an audit trail,
but the restrictions can be enforced only as part of the company's
overall security policy.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Other_Examples"></a>
<h3> <span class="mw-headline"> Other Examples </span></h3>
<p>You can view a comprehensive list of /etc/sudoers file options by issuing the command man sudoers.
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Using_syslog_To_Track_All_sudo_Commands"></a>
<h2> <span class="mw-headline">Using syslog To Track All sudo Commands </span></h2>
<p>All sudo commands are logged in the log file /var/log/messages which
can be very helpful in determining how user error may have contributed
to a problem. All the sudo log entries have the word sudo in them, so
you can easily get a thread of commands used by using the grep command
to selectively filter the output accordingly.
</p>
<p>Here is sample output from a user bob failing to enter their
correct sudo password when issuing a command, immediately followed by
the successful execution of the command /bin/more sudoers.
</p>
<pre>[root@bigboy tmp]# grep sudo /var/log/messages<br />
Nov 18 22:50:30 bigboy sudo(pam_unix)[26812]: authentication failure; logname=bob uid=0 euid=0 tty=pts/0 ruser= rhost= user=bob<br />
Nov 18 22:51:25 bigboy sudo: bob&nbsp;: TTY=pts/0&nbsp;; PWD=/etc&nbsp;; USER=root&nbsp;; COMMAND=/bin/more sudoers<br />
[root@bigboy tmp]#<br />
</pre>
<p><br />
</p>
<a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="Conclusion"></a>
<h1> <span class="mw-headline"> Conclusion </span></h1>
<p>It is important to know how to add users, not just so they can log
in to our system. Most server based applications usually run via a
dedicated unprivileged user account, for example the MySQL database
application runs as user mysql and the Apache Web server application
runs as user apache. These accounts aren't always created
automatically, especially if the software is installed using TAR files.
</p>
<p>Finally, the sudo utility provides a means of dispersing the
responsibility of systems management to multiple users. You can even
give some groups of users only partial access to privileged commands
depending on their roles in the organization. This makes sudo a
valuable part of any company's server administration and security
policy.
</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/241458.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-11-19 19:18 <a href="http://www.blogjava.net/ruoyoux/articles/241458.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OpenSSH Public Key Authentication</title><link>http://www.blogjava.net/ruoyoux/articles/241457.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 19 Nov 2008 11:17:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/241457.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/241457.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/241457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/241457.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/241457.html</trackback:ping><description><![CDATA[<p class="info"><img src="http://sial.org/howto/openssh/publickey-auth/ssh-client-server.png" style="margin: 1em; float: right;" height="193" width="400"  alt="" />Secure Shell (SSH) public key authentication can be used by a client to access servers, if properly configured.</p>
<p class="info">Secure Shell (SSH) public key authentication can be
used by a client to access servers, if properly configured. These notes
describe how to configure <a href="http://www.openssh.com/">OpenSSH</a> for public key authentication, how to enable a <tt class="cmd">ssh-agent</tt> to allow for passphrase-free logins, and <a href="http://sial.org/howto/openssh/publickey-auth/problems/">tips on debugging problems with <acronym title="Secure Shell">SSH</acronym> connections</a>.
Password free logins benefit remote access and automation, for example
if administering many servers or accessing version control software
over <acronym title="Secure Shell">SSH</acronym>.</p>
<p class="info">Public key authenticate can prevent brute force <acronym title="Secure Shell">SSH</acronym> attacks, but only if all password-based authentication methods are disabled. Other options to protect against brute force <acronym title="Secure Shell">SSH</acronym> attacks include <a href="http://sial.org/howto/linux/pam_tally/"><tt class="code">pam_tally</tt></a>, or <a href="http://en.wikipedia.org/wiki/Port_knocking">port knocking</a>. Public key authentication does not work well with <a href="http://sial.org/howto/kerberos/">Kerberos</a> or <a href="http://www.openafs.org/">OpenAFS</a>, which require a password or principal from the client.</p>
<p class="info">Definition of terms used in this documentation:</p>
<ul class="list">
    <li><em class="em">Client</em>: the system one types directly on, such as a laptop or desktop system.<br />
    &nbsp;</li>
    <li><em class="em">Server</em>: anything connected to from the client. This includes other servers accessed through the first server connected to.</li>
</ul>
<p class="info"><em class="em">Never allow root-to-root trust between systems.</em> If required by poorly engineered legacy scripts, limit the <tt class="code">from</tt>
access of the public keys, and if possible only allow specific public
keys to run specific commands. Instead, setup named accounts for users
or roles, and grant as little <tt class="code">root</tt> access as possible via <a href="http://sial.org/howto/sudo/"><tt class="cmd">sudo</tt></a>.</p>
<p class="info">For more information, see also <a href="http://www.amazon.com/dp/0596008953?tag=sialorg-20&amp;link_code=as2&amp;creativeASIN=0596008953&amp;creative=374929&amp;camp=211189" title="ISBN: 0596008953"><span class="book">SSH, The Secure Shell: The Definitive Guide</span></a>. <a href="http://www.sshkeychain.org/">SSHKeyChain</a> offers integration between the <a href="http://www.apple.com/macosx/features/security/">Apple Keychain</a> and OpenSSH.</p>
<h2><a name="s2">Public Key Setup</a></h2>
<div class="subsection"><a href="http://sial.org/howto/openssh/publickey-auth/#s2.1">Key Generation</a> | <a href="http://sial.org/howto/openssh/publickey-auth/#s2.2">Key Distribution</a> | <a href="http://sial.org/howto/openssh/publickey-auth/#s2.3">Key Access Limits</a></div>
<p class="info">First, confirm that OpenSSH is the <acronym title="Secure Shell">SSH</acronym> software installed on the client system. Key generation may vary under different implementations of <acronym title="Secure Shell">SSH</acronym>. The <tt class="cmd">ssh -V</tt> command should print a line beginning with <tt class="code">OpenSSH</tt>, followed by other details.</p>
<p class="data-shell">$ <kbd>ssh -V</kbd><br />
OpenSSH_3.6.1p1+CAN-2003-0693, SSH protocols 1.5/2.0, OpenSSL 0x0090702f</p>
<h3><a name="s2.1">Key Generation</a></h3>
<p class="info">A <tt class="code">RSA</tt>
key pair must be generated on the client system. The public portion of
this key pair will reside on the servers being connected to, while the
private portion needs to remain on a secure local area of the client
system, by default in <tt class="file">~/.ssh/id_rsa</tt>. The key generation can be done with the <a href="http://www.freebsd.org/cgi/man.cgi?query=ssh-keygen&amp;sektion=1&amp;manpath=OpenBSD" title="FreeBSD man page search for ssh-keygen, section 1 on OpenBSD"><tt class="man">ssh-keygen(1)</tt></a> utility.</p>
<p class="data-shell">client$ <kbd>mkdir ~/.ssh</kbd><br />
client$ <kbd>chmod 700 ~/.ssh</kbd><br />
client$ <kbd>ssh-keygen -q -f ~/.ssh/id_rsa -t rsa</kbd><br />
Enter passphrase (empty for no passphrase): &#8230;<br />
Enter same passphrase again: &#8230;</p>
<p class="warn">Do
not use your account password, nor an empty passphrase. The password
should be at least 16 characters long, and not a simple sentence. One
choice would be several lines to a song or poem, interspersed with
punctuation and other non-letter characters. The <tt class="cmd">ssh-agent</tt>
setup notes below will reduce the number of times this passphrase will
need to be used, so using a long passphrase is encouraged.</p>
<p class="info">The
file permissions should be locked down to prevent other users from
being able to read the key pair data. OpenSSH may also refuse to
support public key authentication if the file permissions are too open.
These fixes should be done on all systems involved.</p>
<p class="data-shell">$ <kbd>chmod go-w ~/</kbd><br />
$ <kbd>chmod 700 ~/.ssh</kbd><br />
$ <kbd>chmod go-rwx ~/.ssh/*</kbd></p>
<h3><a name="s2.2">Key Distribution</a></h3>
<p class="info">The public portion of the <tt class="code">RSA</tt>
key pair must be copied to any servers that will be accessed by the
client. The public key information to be copied should be located in
the <tt class="file">~/.ssh/id_rsa.pub</tt> file on the client. Assuming that all of the servers use OpenSSH instead of a different <acronym title="Secure Shell">SSH</acronym> implementation, the public key data must be appended into the <tt class="file">~/.ssh/authorized_keys</tt> file on the servers.</p>
<p class="data-shell"><span class="comment"># first, upload public key from client to server</span><br />
client$ <kbd>scp ~/.ssh/id_rsa.pub server.example.org:</kbd><br />
<br />
<span class="comment"># next, setup the public key on server</span><br />
server$ <kbd>mkdir ~/.ssh</kbd><br />
server$ <kbd>chmod 700 ~/.ssh</kbd><br />
server$ <kbd>cat ~/id_rsa.pub &gt;&gt; ~/.ssh/authorized_keys</kbd><br />
server$ <kbd>chmod 600 ~/.ssh/authorized_keys</kbd><br />
server$ <kbd>rm ~/id_rsa.pub</kbd></p>
<p class="warn">Be sure to append new public key data to the <tt class="file">authorized_keys</tt> file, as multiple public keys may be in use. Each public key entry must be on a different line.</p>
<p class="info">Many
different things can prevent public key authentication from working, so
be sure to confirm that public key connections to the server work
properly. <a href="http://sial.org/howto/openssh/publickey-auth/problems/">If the following test fails, consult the debugging notes</a>.</p>
<p class="data-shell">client$ <kbd>ssh -o PreferredAuthentications=publickey server.example.org</kbd><br />
Enter passphrase for key '/&#8230;/.ssh/id_rsa': &#8230;<br />
&#8230;<br />
server$ <kbd>&nbsp;</kbd></p>
<p class="info">Key distribution can be automated with <a href="http://sial.org/howto/cfengine/modules/authkey/"><tt class="cmd">module:authkey</tt> and CFEngine</a>. This script maps public keys stored in a filesystem repository to specific accounts on various <a href="http://sial.org/howto/cfengine/classes/">classes of systems</a>, allowing a user key to be replicated to all systems the user has access to.</p>
<p class="info">If exporting the public key to a different group or company, consider removing or changing the <a href="http://sial.org/howto/openssh/publickey-auth/comment/">optional public key comment field</a> to avoid exposing the default username and hostname.</p>
<h3><a name="s2.3">Key Access Limits</a></h3>
<p class="info">As an optional step to limit usage of the public key for access to any servers, a <tt class="code">from</tt> statement can be used before public key entries in the <tt class="file">~/.ssh/authorized_keys</tt> file on the servers to limit where the client system is permitted to access the server from. Without a <tt class="code">from</tt>
limit, any client system with the appropriate private key data will be
able to connect to the server from anywhere. If the keypair should only
work when the client system is connecting from a host under <tt class="host">example.org</tt>, set <tt class="code">from="*.example.org"</tt> before the public key data.</p>
<p class="data-shell">server$ <kbd>cat ~/.ssh/authorized_keys</kbd><br />
from="*.example.org" ssh-rsa AAAAB3NzaC1&#8230;</p>
<p class="warn">If a text editor is used to add the <tt class="code">from</tt>
option, ensure the data is saved as a single line; some editors may
wrap the public key and thus corrupt the data. Each public key in the <tt class="file">~/.ssh/authorized_keys</tt> file must not span multiple lines.</p>
<p class="info">Multiple hosts or addresses can be specified as comma separated values. For more information on the syntax of the <tt class="code">from</tt> option, see the <a href="http://www.freebsd.org/cgi/man.cgi?query=sshd&amp;sektion=8&amp;manpath=OpenBSD" title="FreeBSD man page search for sshd, section 8 on OpenBSD"><tt class="man">sshd(8)</tt></a> documentation.</p>
<p class="data">from="*.example.org,10.*,external.example.com" &#8230;</p>
<h2><a name="s3">Configure <tt class="cmd">ssh-agent</tt> Process</a></h2>
<p class="info">To reduce the frequency with which the key passphrase must be typed in, setup a <a href="http://www.freebsd.org/cgi/man.cgi?query=ssh-agent&amp;sektion=1&amp;manpath=OpenBSD" title="FreeBSD man page search for ssh-agent, section 1 on OpenBSD"><tt class="man">ssh-agent(1)</tt></a> daemon to hold the private portion of the <tt class="code">RSA</tt> key pair for the duration of a session. There are several ways to run and manage <tt class="cmd">ssh-agent</tt>, for example from a X11 login script or with a utility like <a href="http://www.gentoo.org/projects/keychain.html">Keychain</a>. These notes rely on the setup of <tt class="cmd">ssh-agent</tt> via an <tt class="code">@reboot</tt> <a href="http://www.freebsd.org/cgi/man.cgi?query=crontab&amp;sektion=5" title="FreeBSD man page search for crontab, section 5"><tt class="man">crontab(5)</tt></a> entry, along with appropriate shell configuration.</p>
<p class="warn">The <tt class="cmd">ssh-agent</tt> must only be run on the client system. The private key of the <tt class="code">RSA</tt>
key pair must remain on the client system. Agent forwarding should be
used to make the key available to subsequent logins to other servers
from the first server connected to.</p>
<ol class="enum">
    <li>Startup cron job</li>
    <p class="info">The following <a href="http://www.freebsd.org/cgi/man.cgi?query=crontab&amp;sektion=5" title="FreeBSD man page search for crontab, section 5"><tt class="man">crontab(5)</tt></a> entry should run the agent at system startup time. The <tt class="cmd">crond</tt> daemon on BSD and Linux systems should support the special <tt class="code">@reboot</tt> syntax required for this to work.</p>
    <p class="data">@reboot ssh-agent -s | grep -v echo &gt; $HOME/.ssh-agent</p>
    <p class="info">To setup the agent for the first time without having to reboot the system, run the following.</p>
    <p class="data-shell">$ <kbd>nohup ssh-agent -s &gt; ~/.ssh-agent</kbd></p>
    <p class="info">Once the <tt class="cmd">ssh-agent</tt> is running, any shells already running will need to source in the environment settings from the <tt class="file">~/.ssh-agent</tt> file. The <tt class="code">SSH_AUTH_SOCK</tt> and <tt class="code">SSH_AGENT_PID</tt> environment variables set in this file are required for the OpenSSH commands such as <tt class="cmd">ssh</tt> and <tt class="cmd">ssh-add</tt> to communicate with the <tt class="cmd">ssh-agent</tt> on the client system.</p>
    <p class="data-shell">$ <kbd>. ~/.ssh-agent</kbd></p>
    <p class="info"><a href="http://sial.org/howto/shell/allsh/">Notes on configuring all shells to be able to run arbitrary commands are available</a>. This reduces the initial setup to the following commands, which can be done from the script <a href="http://sial.org/howto/openssh/publickey-auth/reagent"><tt class="cmd">reagent</tt></a>.</p>
    <p class="data-shell">$ <kbd>nohup ssh-agent -s | grep -v echo &gt; ~/.ssh-agent</kbd><br />
    $ <kbd>allsh - &lt; ~/.ssh-agent</kbd></p>
    <p class="note">If <tt class="cmd">csh</tt> or <tt class="cmd">tcsh</tt> is being used instead of a Bourne-based shell, replace the <tt class="cmd-arg">-s</tt> argument with <tt class="cmd-arg">-c</tt>, and the <tt class="cmd">source</tt> command used instead of <tt class="cmd">.</tt> in any running shells.</p>
    <li>Shell startup script changes</li>
    <p class="info">The shell&#8217;s startup script on the client system will need to be modified to pull in the required environment settings from <tt class="file">~/.ssh-agent</tt> and setup useful aliases. The agent settings in <tt class="file">~/.ssh-agent</tt> should not be read in if the client system is being connected to as a server. Remote connections set the <tt class="code">SSH_CLIENT</tt> environment variable, so <tt class="file">~/.ssh-agent</tt> must not be read in when this variable contains data.</p>
    <p class="data">[ -z "$SSH_CLIENT" ] &amp;&amp; . $HOME/.ssh-agent<br />
    <br />
    alias keyon="ssh-add -t 10800"<br />
    alias keyoff='ssh-add -D'<br />
    alias keylist='ssh-add -l'</p>
    <p class="note">The <tt class="cmd-arg">-t</tt> option to <tt class="cmd">ssh-add</tt>
    will remove keys from memory after the specified number of seconds.
    This option prevents the keys from being left unlocked for long periods
    of time. Older versions of OpenSSH will not have the timeout <tt class="cmd-arg">-t</tt> option.</p>
    <p class="note">For the <tt class="cmd">csh</tt> and <tt class="cmd">tcsh</tt> shells, slightly different configuration of the agent and aliases is required. Consult the relevant <a href="http://www.freebsd.org/cgi/man.cgi?query=ssh-agent&amp;sektion=1" title="FreeBSD man page search for ssh-agent, section 1"><tt class="man">ssh-agent(1)</tt></a> and shell documentation.</p>
</ol>
<p class="info">Once the <tt class="cmd">ssh-agent</tt>
is running and shell configured to read in the appropriate settings and
set easy aliases, enable the key then test a login to a remote server.
The <tt class="cmd">keyon</tt> will only need to be run when initially adding the private key data to <tt class="cmd">ssh-agent</tt>, and only rerun if <tt class="cmd">ssh-agent</tt> is restarted or the key is removed with <tt class="cmd">keyoff</tt>.</p>
<p class="data-shell">client$ <kbd>keyon</kbd><br />
&#8230;<br />
client$ <kbd>ssh server.example.org</kbd><br />
server$ <kbd>exit</kbd><br />
client$ <kbd>keyoff</kbd></p>
<p class="info">Use the <tt class="cmd">keylist</tt> command to see what keys are in the agent process.</p>
<p class="data-shell">$ <kbd>keylist</kbd><br />
1024 01:a1:aa:34:21:bc:7d:a4:ea:56:a4:a1:1a:c5:fa:9f /home/&#8230;/.ssh/id_rsa (RSA)</p>
<p class="info">If password free logins do not work, see <a href="http://sial.org/howto/openssh/publickey-auth/problems/">tips on debugging problems with <acronym title="Secure Shell">SSH</acronym> connections</a> to work out where the problem may be.</p>
<p class="info">To make other applications not run from a shell aware of the agent, the environment definitions in the <tt class="file">~/.ssh-agent</tt>
file will need to be read into the software in question. Consult the
documentation for the software to see whether this is possible.</p>
<h2><a name="s4">Agent Forwarding</a></h2>
<p class="info">For simple client to server connections, <acronym title="Secure Shell">SSH</acronym> agent forwarding will not be a concern. However, if from the server connected to, one logs into other servers, <acronym title="Secure Shell">SSH</acronym> agent forwarding will need to be enabled. If <acronym title="Secure Shell">SSH</acronym>
agent forwarding is disabled, a private key must be available on the
proxy system that is recognized by the server being connected to.</p>
<p class="info">To enable forwarding, either use the <tt class="cmd-arg">-A</tt> option to <tt class="cmd">ssh</tt> when connecting, or set <tt class="code">ForwardAgent</tt> in an OpenSSH <tt class="file">config</tt> file, such as <tt class="file">~/.ssh/config</tt>. Note that command line arguments override the user-specific configuration file, which in turn can override the global <tt class="file">ssh_config</tt> configuration file, if any.</p>
<p class="data">Host *<br />
ForwardAgent yes<br />
ForwardX11 no</p>
<p class="info">Agent
(and X11) forwarding may represent a security risk, providing more
options to an attacker on a compromised server to work back to the
client system. If paranoid, disable Agent and X11 forwarding by
default, and only enable the features where needed. Also enable <tt class="code">StrictHostKeyChecking</tt> and use configuration management software such as <a href="http://sial.org/howto/cfengine/">CFEngine</a> to distribute a global <tt class="file">ssh_known_hosts</tt> file to all client systems.</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/241457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-11-19 19:17 <a href="http://www.blogjava.net/ruoyoux/articles/241457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不用密碼直接用 ssh 登入到遠端電腦</title><link>http://www.blogjava.net/ruoyoux/articles/241456.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 19 Nov 2008 11:16:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/241456.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/241456.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/241456.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/241456.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/241456.html</trackback:ping><description><![CDATA[<p><strong>參考文件</strong></p>
<ul>
    <li>pinfo ssh-keygen</li>
    <li>Linux 伺服器安全防護 (O'REILLY, ISBN: 986-7794-18-4)</li>
</ul>
<p>多年前 telnet 當道，但在安全意識漸漸浮上檯面之後，telnet 在登入時的安全就被大家質疑，後來 ssh (Secure Shell)
出現時，改變了當初的習慣，大家在管理 Linux 時，現在都使用 ssh 來登入，而 ssh 好處我在這也不再多做說明，因為他還可以配合 rsync
做出遠端備份，一旦設定好 ssh 之後，還會有 scp 可以使用！這樣就可以在不同電腦間 copy 檔案，並且為傳輸的資料加密了！ </p>
<p><strong>Shell Script &amp; ssh</strong><br />
自動化的工作可以讓管理員有效率的完成目標，也不用浪費人力和時間做同樣的事情，在無人職守的情況下，要讓 script 自動連入遠端系統做事是件有些麻煩的事，因為您必需登入系統才可以繼續工作，為了不略過登入系統這個步驟，我們可以製做一個
public key 讓遠端的機器信任我們，如此就只要直接連入就可以，而不用再輸入帳號和密碼。</p>
<p><strong>製作 public keys &amp; private keys</strong><br />
利用 ssh-keygen 來做出公用和私有鑰匙，並傳送 public key 到遠端機器使其信任本機登入。</p>
<table border="0" cellpadding="0" cellspacing="0" width="75%">
    <tbody>
        <tr>
            <td class="BbGf">[steven@cute steven]$ ssh-keygen -t dsa<br />
            Generating public/private dsa key pair.<br />
            Enter file in which to save the key (/home/steven/.ssh/id_dsa):<br />
            Enter passphrase (empty for no passphrase): &lt;- 不用輸入<br />
            Enter same passphrase again: &lt;- 不用輸入<br />
            Your identification has been saved in /home/steven/.ssh/id_dsa.<br />
            Your public key has been saved in /home/steven/.ssh/id_dsa.pub.<br />
            The key fingerprint is:<br />
            fa:c9:a9:e4:d5:70:52:88:cc:f3:25:fd:68:ae:c4:4b steven@cute.com.tw<br />
            [steven@cute steven]$</td>
        </tr>
    </tbody>
</table>
<p>接著，再到 /home/steven/.ssh 裡看看，會多出 id_dsa 和 id_dsa.pub 這兩個檔案。</p>
<table border="0" cellpadding="0" cellspacing="0" width="75%">
    <tbody>
        <tr>
            <td class="BbGf">[steven@cute steven]$ cd .ssh<br />
            [steven@cute .ssh]$ ls<br />
            id_dsa id_dsa.pub known_hosts<br />
            [steven@cute .ssh]$</td>
        </tr>
    </tbody>
</table>
<p>現在我們要使遠端機器 mirror.abc.com，使用 sandy 登入時不用輸入密碼，因為，我們應該複製一份 id_dsa.pub
到 sandy@mirror.abc.com 去，並加入到 authorized_keys。</p>
<table border="0" cellpadding="0" cellspacing="0" width="75%">
    <tbody>
        <tr>
            <td class="BbGf">[steven@cute .ssh]$ scp id_dsa.pub sandy@mirror.abc.com:~/id_dsa_steven.pub<br />
            sandy@mirror.abc.com's password:<br />
            id_dsa.pub 100% |*****************************| 607 00:00<br />
            [steven@cute .ssh]$</td>
        </tr>
    </tbody>
</table>
<p>登入 sandy@mirror.abc.com</p>
<table border="0" cellpadding="0" cellspacing="0" width="75%">
    <tbody>
        <tr>
            <td class="BbGf">[steven@cute .ssh]$ ssh sandy@mirror.abc.com<br />
            sandy@mirror.abc.com's password:<br />
            -bash-2.05b$ ls id_dsa_steven.pub<br />
            id_dsa_steven.pub<br />
            -bash-2.05b$ cat id_dsa_steven.pub &gt;&gt; .ssh/authorized_keys<br />
            -bash-2.05b$ exit</td>
        </tr>
    </tbody>
</table>
<p>完成後離開，回到本機，再做一次 ssh 到 mirror.abc.com</p>
<table border="0" cellpadding="0" cellspacing="0" width="75%">
    <tbody>
        <tr>
            <td class="BbGf">[steven@cute .ssh]$ ssh sandy@mirror.abc.com<br />
            -bash-2.05b$</td>
        </tr>
    </tbody>
</table>
<p> <br />
如此就不用輸入密碼就直接登入了！</p>
<p><strong>保護你的私有金匙</strong><br />
在製做 dsa key 時，會有一份私有和一份公有金匙，實務上會保留起來，並做備份，因為當 ssh 在登入時，會使用 id_dsa.pub
和本機的 id_dsa 做確認，因此如果這兩者比對不成功時就會再次要求輸入密碼。</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/241456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-11-19 19:16 <a href="http://www.blogjava.net/ruoyoux/articles/241456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>双系统怎样卸载linux</title><link>http://www.blogjava.net/ruoyoux/articles/238242.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sun, 02 Nov 2008 14:57:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/238242.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/238242.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/238242.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/238242.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/238242.html</trackback:ping><description><![CDATA[<div class="t_msgfont" id="postmessage_4798097">Q: 装了xp（C盘）和fedora4双系统，用grub进行引导，现在想要删掉fedora回收硬盘空间，并且也不要grub引导就能直接进xp，不知道应该怎么操作呢？</div>
<div class="t_msgfont" id="postmessage_4798115">A1: 删除Linux 分区，然后xp 光盘启动，进修复控制台运行 fixmbr 命令。</div>
<div class="t_msgfont" id="postmessage_4798140">A2:&nbsp;win下右键单击我的电脑——&amp;gt;管理——&amp;gt;磁盘管理。这样可以看见硬盘的分区情况，把属于linux的分区删除。合并成win下的分区。这样硬盘空间就回收了<br />
&nbsp; &nbsp; 至于不用grub引导的问题，找一张xp系统盘进入dos下用 fdisk /mbr命令就可以删除grub。</div>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/238242.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-11-02 22:57 <a href="http://www.blogjava.net/ruoyoux/articles/238242.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>