Gentoo Archives: gentoo-doc-cvs

From: Shyam Mani <fox2mike@×××××××××××.org>
To: gentoo-doc-cvs@l.g.o
Subject: [gentoo-doc-cvs] cvs commit: bash-by-example-p2.xml
Date: Thu, 14 Jul 2005 18:03:39
Message-Id: 200507141803.j6EI3JG0019975@robin.gentoo.org
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