1 |
fox2mike 05/07/14 18:03:09 |
2 |
|
3 |
Added: xml/htdocs/doc/en/articles bash-by-example-p2.xml |
4 |
bash-by-example-p3.xml |
5 |
Log: |
6 |
#99008 - Bash by example, parts 2 and 3, initial version. Thanks to Lukasz Damentko. |
7 |
|
8 |
Revision Changes Path |
9 |
1.1 xml/htdocs/doc/en/articles/bash-by-example-p2.xml |
10 |
|
11 |
file : http://www.gentoo.org/cgi-bin/viewcvs.cgi/xml/htdocs/doc/en/articles/bash-by-example-p2.xml?rev=1.1&content-type=text/x-cvsweb-markup&cvsroot=gentoo |
12 |
plain: http://www.gentoo.org/cgi-bin/viewcvs.cgi/xml/htdocs/doc/en/articles/bash-by-example-p2.xml?rev=1.1&content-type=text/plain&cvsroot=gentoo |
13 |
|
14 |
Index: bash-by-example-p2.xml |
15 |
=================================================================== |
16 |
<?xml version='1.0' encoding="UTF-8"?> |
17 |
<!-- $Header: /var/cvsroot/gentoo/xml/htdocs/doc/en/articles/bash-by-example-p2.xml,v 1.1 2005/07/14 18:03:09 fox2mike Exp $ --> |
18 |
<!DOCTYPE guide SYSTEM "/dtd/guide.dtd"> |
19 |
|
20 |
<guide link="/doc/en/articles/bash-by-example-part2.xml"> |
21 |
<title>Bash by example, Part 2</title> |
22 |
|
23 |
<author title="Author"> |
24 |
<mail link="drobbins@g.o">Daniel Robbins</mail> |
25 |
</author> |
26 |
<author title="Editor"> |
27 |
<mail link="rane@××××××.pl">Łukasz Damentko</mail> |
28 |
</author> |
29 |
|
30 |
<abstract> |
31 |
In his introductory article on bash, Daniel Robbins walked you through some of |
32 |
the scripting language's basic elements and reasons for using bash. In this, the |
33 |
second installment, Daniel picks up where he left off and looks at bash's basic |
34 |
constructs like conditional (if-then) statements, looping, and more. |
35 |
</abstract> |
36 |
|
37 |
<!-- The original version of this article was published on IBM developerWorks, |
38 |
and is property of Westtech Information Services. This document is an updated |
39 |
version of the original article, and contains various improvements made by the |
40 |
Gentoo Linux Documentation team --> |
41 |
|
42 |
<version>1.0</version> |
43 |
<date>2005-07-14</date> |
44 |
|
45 |
<chapter> |
46 |
<title>More bash programming fundamentals</title> |
47 |
<section> |
48 |
<title>Accepting arguments</title> |
49 |
<body> |
50 |
|
51 |
<note> |
52 |
The original version of this article was published on IBM developerWorks, and |
53 |
is property of Westtech Information Services. This document is an updated |
54 |
version of the original article, and contains various improvements made by the |
55 |
Gentoo Linux Documentation team. |
56 |
</note> |
57 |
|
58 |
<p> |
59 |
Let's start with a brief tip on handling command-line arguments, and then look |
60 |
at bash's basic programming constructs. |
61 |
</p> |
62 |
|
63 |
<p> |
64 |
In the sample program in the <uri |
65 |
link="/doc/en/articles/bash-by-example-p1.xml">introductory article</uri>, we |
66 |
used the environment variable "$1", which referred to the first command-line |
67 |
argument. Similarly, you can use "$2", "$3", etc. to refer to the second and |
68 |
third arguments passed to your script. Here's an example: |
69 |
</p> |
70 |
|
71 |
<pre caption="Referring to arguments passed to the script"> |
72 |
#!/usr/bin/env bash |
73 |
|
74 |
echo name of script is $0 |
75 |
echo first argument is $1 |
76 |
echo second argument is $2 |
77 |
echo seventeenth argument is $17 |
78 |
echo number of arguments is $# |
79 |
</pre> |
80 |
|
81 |
<p> |
82 |
The example is self explanatory except for two small details. First, "$0" will |
83 |
expand to the name of the script, as called from the command line, and "$#" will |
84 |
expand to the number of arguments passed to the script. Play around with the |
85 |
above script, passing different kinds of command-line arguments to get the hang |
86 |
of how it works. |
87 |
</p> |
88 |
|
89 |
<p> |
90 |
Sometimes, it's helpful to refer to all command-line arguments at once. For this |
91 |
purpose, bash features the "$@" variable, which expands to all command-line |
92 |
parameters separated by spaces. We'll see an example of its use when we take a |
93 |
look at "for" loops, a bit later in this article. |
94 |
</p> |
95 |
|
96 |
</body> |
97 |
</section> |
98 |
<section> |
99 |
<title>Bash programming constructs</title> |
100 |
<body> |
101 |
|
102 |
<p> |
103 |
If you've programmed in a procedural language like C, Pascal, Python, or Perl, |
104 |
then you're familiar with standard programming constructs like "if" statements, |
105 |
"for" loops, and the like. Bash has its own versions of most of these standard |
106 |
constructs. In the next several sections, I will introduce several bash |
107 |
constructs and demonstrate the differences between these constructs and others |
108 |
you are already familiar with from other programming languages. If you haven't |
109 |
programmed much before, don't worry. I include enough information and examples |
110 |
so that you can follow the text. |
111 |
</p> |
112 |
|
113 |
</body> |
114 |
</section> |
115 |
<section> |
116 |
<title>Conditional love</title> |
117 |
<body> |
118 |
|
119 |
<p> |
120 |
If you've ever programmed any file-related code in C, you know that it requires |
121 |
a significant amount of effort to see if a particular file is newer than |
122 |
another. That's because C doesn't have any built-in syntax for performing such a |
123 |
comparison; instead, two stat() calls and two stat structures must be used to |
124 |
perform the comparison by hand. In contrast, bash has standard file comparison |
125 |
operators built in, so determining if "<path>/tmp/myfile</path> is readable" is |
126 |
as easy as checking to see if "<c>$myvar</c> is greater than 4". |
127 |
</p> |
128 |
|
129 |
<p> |
130 |
The following table lists the most frequently used bash comparison operators. |
131 |
You'll also find an example of how to use every option correctly. The example is |
132 |
meant to be placed immediately after the "if". For example: |
133 |
</p> |
134 |
|
135 |
<pre caption="Bash comparison operator"> |
136 |
if [ -z "$myvar" ] |
137 |
then |
138 |
echo "myvar is not defined" |
139 |
fi |
140 |
</pre> |
141 |
|
142 |
<p> |
143 |
Sometimes, there are several different ways that a particular comparison can be |
144 |
made. For example, the following two snippets of code function identically: |
145 |
</p> |
146 |
|
147 |
<pre caption="Two ways of making comparison"> |
148 |
if [ "$myvar" -eq 3 ] |
149 |
then |
150 |
echo "myvar equals 3" |
151 |
fi |
152 |
|
153 |
if [ "$myvar" = "3" ] |
154 |
then |
155 |
echo "myvar equals 3" |
156 |
fi |
157 |
</pre> |
158 |
|
159 |
<p> |
160 |
In the above two comparisons do exactly the same thing, but the first uses |
161 |
arithmetic comparison operators, while the second uses string comparison |
162 |
operators. |
163 |
</p> |
164 |
|
165 |
</body> |
166 |
</section> |
167 |
<section> |
168 |
<title>String comparison caveats</title> |
169 |
<body> |
170 |
|
171 |
<p> |
172 |
Most of the time, while you can omit the use of double quotes surrounding |
173 |
strings and string variables, it's not a good idea. Why? Because your code will |
174 |
work perfectly, unless an environment variable happens to have a space or a tab |
175 |
in it, in which case bash will get confused. Here's an example of a fouled-up |
176 |
comparison: |
177 |
</p> |
178 |
|
179 |
<pre caption="Fouled-up comparison example"> |
180 |
if [ $myvar = "foo bar oni" ] |
181 |
then |
182 |
echo "yes" |
183 |
fi |
184 |
</pre> |
185 |
|
186 |
<p> |
187 |
In the above example, if myvar equals "foo", the code will work as expected and |
188 |
not print anything. However, if myvar equals "foo bar oni", the code will fail |
189 |
with the following error: |
190 |
</p> |
191 |
|
192 |
<pre caption="Error when variable contains spaces"> |
193 |
[: too many arguments |
194 |
</pre> |
195 |
|
196 |
<p> |
197 |
In this case, the spaces in "$myvar" (which equals "foo bar oni") end up |
198 |
confusing bash. After bash expands "$myvar", it ends up with the following |
199 |
comparison: |
200 |
</p> |
201 |
|
202 |
<pre caption="Ending comparison"> |
203 |
[ foo bar oni = "foo bar oni" ] |
204 |
</pre> |
205 |
|
206 |
<p> |
207 |
Because the environment variable wasn't placed inside double quotes, bash thinks |
208 |
that you stuffed too many arguments in-between the square brackets. You can |
209 |
easily eliminate this problem by surrounding the string arguments with |
210 |
double-quotes. Remember, if you get into the habit of surrounding all string |
211 |
arguments and environment variables with double-quotes, you'll eliminate many |
212 |
similar programming errors. Here's how the "foo bar oni" comparison should have |
213 |
been written: |
214 |
</p> |
215 |
|
216 |
|
217 |
|
218 |
1.1 xml/htdocs/doc/en/articles/bash-by-example-p3.xml |
219 |
|
220 |
file : http://www.gentoo.org/cgi-bin/viewcvs.cgi/xml/htdocs/doc/en/articles/bash-by-example-p3.xml?rev=1.1&content-type=text/x-cvsweb-markup&cvsroot=gentoo |
221 |
plain: http://www.gentoo.org/cgi-bin/viewcvs.cgi/xml/htdocs/doc/en/articles/bash-by-example-p3.xml?rev=1.1&content-type=text/plain&cvsroot=gentoo |
222 |
|
223 |
Index: bash-by-example-p3.xml |
224 |
=================================================================== |
225 |
<?xml version='1.0' encoding="UTF-8"?> |
226 |
<!-- $Header: /var/cvsroot/gentoo/xml/htdocs/doc/en/articles/bash-by-example-p3.xml,v 1.1 2005/07/14 18:03:09 fox2mike Exp $ --> |
227 |
<!DOCTYPE guide SYSTEM "/dtd/guide.dtd"> |
228 |
|
229 |
<guide link="/doc/en/articles/bash-by-example-part3.xml"> |
230 |
<title>Bash by example, Part 3</title> |
231 |
|
232 |
<author title="Author"> |
233 |
<mail link="drobbins@g.o">Daniel Robbins</mail> |
234 |
</author> |
235 |
<author title="Editor"> |
236 |
<mail link="rane@××××××.pl">Łukasz Damentko</mail> |
237 |
</author> |
238 |
|
239 |
<abstract> |
240 |
In his final Bash by example article, Daniel Robbins takes a good look at the |
241 |
Gentoo Linux ebuild system, an excellent example of the power of bash. Step by |
242 |
step, he shows you how the ebuild system was implemented, and touches on many |
243 |
handy bash techniques and design strategies. By the end of the article, you'll |
244 |
have a good grasp of what's involved in producing a full-blown bash-based |
245 |
application, as well as a start at coding your own auto-build system. |
246 |
</abstract> |
247 |
|
248 |
<!-- The original version of this article was published on IBM developerWorks, |
249 |
and is property of Westtech Information Services. This document is an updated |
250 |
version of the original article, and contains various improvements made by the |
251 |
Gentoo Linux Documentation team --> |
252 |
|
253 |
<version>1.0</version> |
254 |
<date>2005-07-14</date> |
255 |
|
256 |
<chapter> |
257 |
<title>Exploring the ebuild system</title> |
258 |
<section> |
259 |
<title>Enter the ebuild system</title> |
260 |
<body> |
261 |
|
262 |
<note> |
263 |
The original version of this article was published on IBM developerWorks, and |
264 |
is property of Westtech Information Services. This document is an updated |
265 |
version of the original article, and contains various improvements made by the |
266 |
Gentoo Linux Documentation team. |
267 |
</note> |
268 |
|
269 |
<p> |
270 |
I've really been looking forward to this third and final <e>Bash by example</e> |
271 |
article, because now that we've already covered bash programming fundamentals in |
272 |
<uri link="/doc/en/articles/bash-by-example-p1.xml">Part 1</uri> and <uri |
273 |
link="/doc/en/articles/bash-by-example-p2.xml">Part 2</uri>, we can focus on |
274 |
more advanced topics, like bash application development and program design. For |
275 |
this article, I will give you a good dose of practical, real-world bash |
276 |
development experience by presenting a project that I've spent many hours coding |
277 |
and refining: The Gentoo Linux ebuild system. |
278 |
</p> |
279 |
|
280 |
<p> |
281 |
I'm the chief architect of Gentoo Linux, a next-generation Linux OS currently in |
282 |
beta. One of my primary responsibilities is to make sure that all of the binary |
283 |
packages (similar to RPM packages) are created properly and work together. As |
284 |
you probably know, a standard Linux system is not composed of a single unified |
285 |
source tree (like BSD), but is actually made up of about 25+ core packages that |
286 |
work together. Some of the packages include: |
287 |
</p> |
288 |
|
289 |
<table> |
290 |
<tr> |
291 |
<th>Package</th> |
292 |
<th>Description</th> |
293 |
</tr> |
294 |
<tr> |
295 |
<ti>linux</ti> |
296 |
<ti>The actual kernel</ti> |
297 |
</tr> |
298 |
<tr> |
299 |
<ti>util-linux</ti> |
300 |
<ti>A collection of miscellaneous Linux-related programs</ti> |
301 |
</tr> |
302 |
<tr> |
303 |
<ti>e2fsprogs</ti> |
304 |
<ti>A collection of ext2 filesystem-related utilities</ti> |
305 |
</tr> |
306 |
<tr> |
307 |
<ti>glibc</ti> |
308 |
<ti>The GNU C library</ti> |
309 |
</tr> |
310 |
</table> |
311 |
|
312 |
<p> |
313 |
Each package is in its own tarball and is maintained by separate independent |
314 |
developers, or teams of developers. To create a distribution, each package has |
315 |
to be separately downloaded, compiled, and packaged. Every time a package must |
316 |
be fixed, upgraded, or improved, the compilation and packaging steps must be |
317 |
repeated (and this gets old really fast). To help eliminate the repetitive steps |
318 |
involved in creating and updating packages, I created the ebuild system, written |
319 |
almost entirely in bash. To enhance your bash knowledge, I'll show you how I |
320 |
implemented the unpack and compile portions of the ebuild system, step by step. |
321 |
As I explain each step, I'll also discuss why certain design decisions were |
322 |
made. By the end of this article, not only will you have an excellent grasp of |
323 |
larger-scale bash programming projects, but you'll also have implemented a good |
324 |
portion of a complete auto-build system. |
325 |
</p> |
326 |
|
327 |
</body> |
328 |
</section> |
329 |
<section> |
330 |
<title>Why bash?</title> |
331 |
<body> |
332 |
|
333 |
<p> |
334 |
Bash is an essential component of the Gentoo Linux ebuild system. It was chosen |
335 |
as ebuild's primary language for a number of reasons. First, it has an |
336 |
uncomplicated and familiar syntax that is especially well suited for calling |
337 |
external programs. An auto-build system is "glue code" that automates the |
338 |
calling of external programs, and bash is very well suited to this type of |
339 |
application. Second, Bash's support for functions allowed the ebuild system to |
340 |
have modular, easy-to-understand code. Third, the ebuild system takes advantage |
341 |
of bash's support for environment variables, allowing package maintainers and |
342 |
developers to configure it easily, on-the-fly. |
343 |
</p> |
344 |
|
345 |
</body> |
346 |
</section> |
347 |
<section> |
348 |
<title>Build process review</title> |
349 |
<body> |
350 |
|
351 |
<p> |
352 |
Before we look at the ebuild system, let's review what's involved in getting a |
353 |
package compiled and installed. For our example, we will look at the "sed" |
354 |
package, a standard GNU text stream editing utility that is part of all Linux |
355 |
distributions. First, download the source tarball (<path>sed-3.02.tar.gz</path>) |
356 |
(see <uri link="#resources">Resources</uri>). We will store this archive in |
357 |
<path>/usr/src/distfiles</path>, a directory we will refer to using the |
358 |
environment variable <c>$DISTDIR</c>. <c>$DISTDIR</c> is the directory where all |
359 |
of our original source tarballs live; it's a big vault of source code. |
360 |
</p> |
361 |
|
362 |
<p> |
363 |
Our next step is to create a temporary directory called <path>work</path>, which |
364 |
houses the uncompressed sources. We'll refer to this directory later using the |
365 |
<c>$WORKDIR</c> environment variable. To do this, change to a directory where we |
366 |
have write permission and type the following: |
367 |
</p> |
368 |
|
369 |
<pre caption="Uncompressing sed into a temporary directory"> |
370 |
$ <i>mkdir work</i> |
371 |
$ <i>cd work</i> |
372 |
$ <i>tar xzf /usr/src/distfiles/sed-3.02.tar.gz</i> |
373 |
</pre> |
374 |
|
375 |
<p> |
376 |
The tarball is then decompressed, creating a directory called |
377 |
<path>sed-3.02</path> that contains all of the sources. We'll refer to the |
378 |
<path>sed-3.02</path> directory later using the environment variable |
379 |
<c>$SRCDIR</c>. To compile the program, type the following: |
380 |
</p> |
381 |
|
382 |
<pre caption="Uncompressing sed into a temporary directory"> |
383 |
$ <i>cd sed-3.02</i> |
384 |
$ <i>./configure --prefix=/usr</i> |
385 |
<comment>(autoconf generates appropriate makefiles, this can take a while)</comment> |
386 |
|
387 |
$ <i>make</i> |
388 |
|
389 |
<comment>(the package is compiled from sources, also takes a bit of time)</comment> |
390 |
</pre> |
391 |
|
392 |
<p> |
393 |
We're going to skip the "make install" step, since we are just covering the |
394 |
unpack and compile steps in this article. If we wanted to write a bash script to |
395 |
perform all these steps for us, it could look something like this: |
396 |
</p> |
397 |
|
398 |
<pre caption="Sample bash script to perform the unpack/compile process"> |
399 |
#!/usr/bin/env bash |
400 |
|
401 |
if [ -d work ] |
402 |
then |
403 |
<comment># remove old work directory if it exists</comment> |
404 |
rm -rf work |
405 |
fi |
406 |
mkdir work |
407 |
cd work |
408 |
tar xzf /usr/src/distfiles/sed-3.02.tar.gz |
409 |
cd sed-3.02 |
410 |
./configure --prefix=/usr |
411 |
make |
412 |
</pre> |
413 |
|
414 |
</body> |
415 |
</section> |
416 |
<section> |
417 |
<title>Generalizing the code</title> |
418 |
<body> |
419 |
|
420 |
<p> |
421 |
Although this autocompile script works, it's not very flexible. Basically, the |
422 |
bash script just contains the listing of all the commands that were typed at the |
423 |
command line. While this solution works, it would be nice to make a generic |
424 |
|
425 |
|
426 |
|
427 |
-- |
428 |
gentoo-doc-cvs@g.o mailing list |