[ 前のページ ] [ 目次 ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ 14 ] [ 15 ] [ A ] [ 次のページ ]

Debian レファレンス
第 13 章 - プログラミング


実行用テストファイルの名前として "test" を使うのは止めましょう。 test というコマンドがシェル組込みコマンドにあります。


13.1 始め方

References:

多量の info 文書が書籍として GNU から得られます。

次の4章には、newusers プログラムのようなバッチプロセッサを 用いて /etc/passwd にアカウント情報を追加するための数種類の 言語によるサンプルスクリプトが含まれます。スクリプトは first_name last_name password の形式の数行の入力ファイルを必要と します。(実際ユーザのホームディレクトリはこれらのスクリプトによって 作成されません。)


13.2 シェル

Unix ライクなシステムの働きを理解する最良の方法は、 シェルスクリプトを読むことです。ここで、シェルプログラムに関する いくつかのポイントと注意をあたえます。間違いから学ぶには、 Shell Mistakes を読んでください。


13.2.1 Bash – GNU 標準の対話シェル

Bash リファレンス:

次に短いプログラム例を示します(標準入力から newusers 用の アカウントエントリを作成):

     #!/bin/bash
     # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
     pid=1000;
     while read n1 n2 n3 ; do
     if [ ${n1:0:1} != "#" ]; then
     let pid=$pid+1
     echo ${n1}_${n2}:password:${pid}:${pid}:,,,/home/${n1}_${n2}:/bin/bash
     fi
     done

13.2.2 POSIX シェル

Several packages provide a POSIX shell in Debian: Debian では、数種類のパッケージが POSIX シェルを供給します:

移植性を考慮してシェルスクリプトを作成している場合、POSIX シェルスクリプト としてスクリプトを書くのが最良です。シェルスクリプトの POSIX 互換性を テストするには、ash (又は dash) にリンクされた /bin/sh を使用してください。csh 文法に似たように 見える bashism 又は zshism を用いて スクリプトを作るのは避けましょう。 例えば、次のような表現は避けましょう:

本文書におけるシェルの記述方法は POSIX タイプのシェルのみを用いており、 それゆえ、tcsh を含む csh タイプのシェルは 使用していません。


13.2.3 シェルパラメータ

いくつかの特別なパラメータを覚える必要があります:

     $0      = シェル又はシェルスクリプトの名前
     $1      = シェルの第1引数
      ...
     $9      = シェルの第9引数
     $#      = number of positional parameters
     "$*"    = "$1 $2 $3 $4 ... $n"
     "$@"    = "$1" "$2" "$3" "$4" ... "$n"
     $?      = 最後のコマンドの exit status 
     $$      = シェルスクリプトの PID 
     $!      = 最後に起動されたバックグラウンドジョブの PID

基本的なパラメータ拡張を覚える必要があります:

         Form        If var is set       If var is not set
     ${var:-string}  $var                string
     ${var:+string}  string              null
     ${var:=string}  $var                string 
                                         (and run var=string)
     ${var:?string}  $var                (echo string and then exit)

ここで、これらの演算子全てにおいて、コロン `:' は実際は無くても構いません。

Basic parameter substitutions to remember:

         Form        Result
     ${var%suffix}   Remove smallest suffix pattern
     ${var%%suffix}  Remove largest suffix pattern
     ${var#prefix}   Remove smallest prefix pattern
     ${var##prefix}  Remove largest prefix pattern

13.2.4 Shell redirection

Basic redirection to remember (here the [n] is an optional number to specify the file descriptor):

     [n]> file      Redirect stdout (or n) to file.
     [n]>> file     Append stdout (or n) to file.
     [n]< file      Redirect stdin (or n) from file.
     [n1]>&n2       Redirect stdout (or n1) to n2.
     2> file  >&2   Redirect stdout and stderr to file.
      > file 2>&1   Redirect stdout and stderr to file.
     | command      Pipe stdout to command.
     2>&1 | command Pipe stderr and stdout to command.

Here,

The shell allows you to open files using the exec builtin with an arbitual file descriptor.

     $ echo Hello >foo
     $ exec 3<foo 4>bar  # open files
     $ cat <&3 >&4       # redirect stdin to 3, stdout to 4
     $ exec 3<&- 4>&-    # close files
     $ cat bar
     Hello

Here n<&- and n>&- mean to close the file descriptor n.


13.2.5 Shell conditionals

Each command returns an exit status which can be used for conditional expressions:

Note that the use here of a 0 value to mean "true" differs from the usual convention in some other areas of computing. Also, `[' is the equivalent of the test command, which evaluates its arguments up to `]' as a conditional expression.

Basic conditional idioms to remember are:

     command && if_success_run_this_command_too || true
     command || if_not_success_run_this_command_instead
     
     if [ conditional_expression ]; then  
      if_success_run_this_command
     else
      if_not_success_run_this_command
     fi

Here || true was needed to ensure this shell script will not exit at this line accidentally when shell is invoked with -e flag.

File comparison operators in the conditional expression are:

     -e file         True if file exists.
     -d file         True if file exists and is a directory.
     -f file         True if file exists and is a regular file.
     -w file         True if file exists and is writable.
     -x file         True if file exists and is executable.
     file1 -nt file2 True if file1 is newer than file2. (modification)
     file1 -ot file2 True if file1 is older than file2. (modification)
     file1 -ef file2 True if they are the same device and inode numbers.

String comparison operators in the conditional expression are:

          -z str    True if the length of str is zero.
          -n str    True if the length of str is non-zero.
     str1 == str2   True if the strings are equal.
     str1 =  str2   True if the strings are equal.
         ("=" should be used in place of "==" for strict POSIX compliance) 
     str1 != str2   True if the strings are not equal.
     str1 <  str2   True if str1 sorts before str2 (locale dependent).
     str1 >  str2   True if str1 sorts after str2 (locale dependent).

Arithmetic integer comparison operators in the conditional expression are -eq, -ne, -lt, -le, -gt, and -ge.


13.2.6 Command-line processing

The shell processes a script as follows:

Single quotes within double quotes have no effect.

Executing set -x in the shell or invoking the shell with -x option make the shell to print all of commands executed. This is quite handy for debugging.


13.3 Awk

References for Awk:

Short program example (creates newusers command entry):

     #!/usr/bin/awk -f
     # Script to create a file suitable for use in the 'newusers' command,
     # from a file consisting of user IDs and passwords in the form:
     # first_name last_name password
     # Copyright (c) KMSelf Sat Aug 25 20:47:38 PDT 2001
     # Distributed under GNU GPL v 2, or at your option, any later version.
     # This program is distributed WITHOUT ANY WARRANTY.
     
     BEGIN {
         # Assign starting UID, GID
         if ( ARGC > 2 ) {
             startuid = ARGV[1]
             delete ARGV[1]
         }
         else {
             printf( "Usage:  newusers startUID file\n" \
               "  where:\n" \ 
               "    startUID is the starting userid to add, and\n" \
               "    file is an input file in form:\n" \
               "      first_name last_name password\n" \
             )
             exit
         }
     
         infile = ARGV[1]
         printf( "Starting UID: %s\n\n", startuid )
     }
     
     /^#/ { next }
     
     {
         ++record
         first = $1
         last = $2
         passwd = $3
         user= substr( tolower( first ), 1, 1 ) tolower( last )
         uid = startuid + record - 1
         gid = uid
         printf( "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n",  \
             user, passwd, uid, gid, first, last, user \
             )
     }

Two packages provide POSIX awk in Debian:


13.4 Perl

This is the interpreter on a Unix-like system.

References for Perl:

Short program example (creates newusers command entry):

     #!/usr/bin/perl
     # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
     $pid=1000;
     while (<STDIN>) {
             if (/^#/) { next;}
             chop;
             $pid++;
             ($n1, $n2, $n3) = split / /;
             print $n1,"_",$n2,":", $n3, ":",$pid,
                       ":",$pid,",,,/home/",$n1,"_",$n2,":/bin/bash\n"
     }

Install Perl module module_name:

     # perl -MCPAN -e 'install module_name'

13.5 Python

It's a nice object-oriented interpreter.

References for Python:

Short program example (creates newusers command entry):

     #! /usr/bin/env python
     import sys, string
     
     # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
     # Ported from awk script by KMSelf Sat Aug 25 20:47:38 PDT 2001
     # This program is distributed WITHOUT ANY WARRANTY.
     
     def usages():
         print \
     "Usage:  ", sys.argv[0], " start_UID [filename]\n" \
     "\tstartUID is the starting userid to add.\n" \
     "\tfilename is input filename. If not specified, standard input.\n\n" \
     "Input file format:\n"\
     "\tfirst_name last_name password\n"
                     return 1
     
     def parsefile(startuid):
         #
         # main filtering
         #
         uid = startuid
         while 1:
             line = infile.readline()
             if not line:
                 break
             if line[0] == '#':
                 continue
             (first, last, passwd) = string.split(string.lower(line))
             # above crashes with wrong # of parameters :-)
             user = first[0] + last
             gid = uid
             lineout = "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n" %  \
                 (user, passwd, uid, gid, first, last, user)
             sys.stdout.write(lineout)
             +uid
     
     if __name__ == '__main__':
         if len(sys.argv) == 1:
             usages()
         else:
             uid = int(sys.argv[1])
             #print "# UID start from: %d\n" % uid
             if len(sys.argv) > 1:
                 infilename   = string.join(sys.argv[2:])
                 infile = open(infilename, 'r')
                 #print "# Read file from: %s\n\n" % infilename
             else:
                 infile = sys.stdin
             parsefile(uid)

13.6 Make

References for Make:

Simple automatic variables:

Rule syntax:

     target: [ prerequisites ... ]
      [TAB]  command1
      [TAB]  -command2 # ignore errors
      [TAB]  @command3 # suppress echoing

Here [TAB] is a TAB code. Each line is interpreted by the shell after make variable substitution. Use \ at the end of a line to continue the script. Use $$ to enter $ for environment values for a shell script.

Implicit rules for the target and prerequisites can be written, for example, as:

     %: %.c header.h

or,

     %.o: %.c header.h

Here, the target contains the character % (exactly one of them). The % can match any nonempty substring in the actual target filenames. The prerequisites likewise use % to show how their names relate to the actual target name.

Suffix rules are the obsolete way of defining implicit rules for make. They are still supported in GNU make for compatibility, but use equivalent pattern rules whenever possible:

     old suffix rule --> new pattern rule
     .c:             --> %  : %.c
     .c.o:           --> %.o: %.c

Automatic variables for the rule:

     foo.o: new1.c new2.c old1.c new3.c
     $@ == foo.o                         (target)
     $< == new1.c                        (first one)
     $? == new1.c new2.c new3.c          (newer ones)
     $^ == new1.c new2.c old1.c new3.c   (all)
     $* == `%' matched stem in the target pattern.

Variable references:

     foo1 := bar    # One-time expansion
     foo2  = bar    # Recursive expansion
     foo3 += bar    # Append
     SRCS := $(wildcard *.c)
     OBJS := $(foo:c=o)
     OBJS := $(foo:%.c=%.o) 
     OBJS := $(patsubst %.c,%.o,$(foo)) 
     DIRS  = $(dir directory/filename.ext) # Extracts "directory"
      $(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ...

Run make -p -f/dev/null to see automatic internal rules.


13.7 C

Preparation:

     # apt-get install glibc-doc manpages-dev libc6-dev gcc

References for C:


13.7.1 Simple C program (gcc)

A simple example to compile example.c with a library libm into an executable run_example:

     $ cat > example.c << EOF
     #include <stdio.h>
     #include <math.h>
     #include <string.h>
     
     int main(int argc, char **argv, char **envp){
             double x;
             char y[11];
             x=sqrt(argc+7.5);
             strncpy(y, argv[0], 10); /* prevent buffer overflow */
             y[10] = '\0'; /* fill to make sure string ends with '\0' */
             printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]);
             return 0;
     }
     EOF
     $ gcc -Wall -g -o run_example example.c -lm
     $ ./run_example
             1, 2.915, ./run_exam,     (null)
     $ ./run_example 1234567890qwerty
             2, 3.082, ./run_exam, 1234567890qwerty

Here, -lm is needed to link library libm for sqrt(). The actual library is in /lib/ with filename libm.so.6, which is a symlink to libm-2.1.3.so.

Look at the last parameter in the output text. There are more than 10 characters even though %10s is specified.

The use of pointer memory operation functions without boundary checks, such as sprintf and strcpy, is deprecated to prevent buffer overflow exploits that leverage the above overrun effects. Instead, use snprintf and strncpy.


13.7.2 Debugging


13.7.2.1 Debugging with gdb

Preparation:

     # apt-get install gdb

References for gdb:

Use gdb to debug a program compiled with the -g option. Many commands can be abbreviated. Tab expansion works as in the shell.

     $ gdb program
     (gdb) b 1                # set breakpoint at line 1
     (gdb) run arg1 arg2 arg3 # run program
     (gdb) next               # next line
     ...
     (gdb) step               # step forward
     ...
     (gdb) p parm             # print parm 
     ...
     (gdb) p parm=12          # set value to 12

For debugging from within Emacs, refer to エディタのコマンドサマリ (Emacs, Vim), 第 11.3.4 節.


13.7.2.2 Check dependency on libraries

Use ldd to find out a program's dependency on libraries:

     $ ldd /bin/ls
             librt.so.1 => /lib/librt.so.1 (0x4001e000)
             libc.so.6 => /lib/libc.so.6 (0x40030000)
             libpthread.so.0 => /lib/libpthread.so.0 (0x40153000)
             /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

For ls to work in a chrooted environment, the above libraries must be available in your chrooted environment.

The following commands will also be useful:


13.7.2.3 Debugging with memory leak detection tools

There are several memory leak detection tools available in Debian.

Also check out Debugging Tools for Dynamic Storage Allocation and Memory Management.


13.7.3 Flex – a better Lex

flex is a fast lexical analyzer generator.

References for flex:

You need to provide your own main() and yywrap(), or your program.l should look like this to compile without a library (yywrap is a macro; %option main turns on %option noyywrap implicitly):

     %option main
     %%
     .|\n    ECHO ;
     %%

Alternatively, you may compile with the -lfl linker option at the end of your cc command line (like AT&T-Lex with -ll). No %option is needed in this case.


13.7.4 Bison – a better Yacc

Several packages provide a Yacc-compatible LALR parser generator in Debian:

References for bison:

You need to provide your own main() and yyerror(). main() calls yyparse() which calls yylex(), usually created with FleX.

     %%
     
     %%

13.7.5 Autoconf

autoconf is a tool for producing shell scripts that automatically configure software source code packages to adapt to many kinds of UNIX-like systems using the entire GNU build system.

autoconf produces the configuration script configure. configure automatically creates a customized Makefile using the Makefile.in template.


13.7.5.1 Compile and install a program

Debian does not touch files in /usr/local (see 多様性のサポート, 第 2.5 節). So if you compile a program from source, install it into /usr/local so it will not interfere with Debian.

     $ cd src
     $ ./configure --prefix=/usr/local
     $ make
     $ make install # this puts the files in the system

13.7.5.2 Uninstall program

If you still have the source and if it uses autoconf/automake and if you can remember how you configured it:

     $ ./configure all-of-the-options-you-gave-it
     # make uninstall

Alternatively, if you are absolutely sure that the install process puts files only under /usr/local and there is nothing important there, you can erase all its contents by:

     # find /usr/local -type f -print0 | xargs -0 rm -f

If you are not sure where files are installed, you should consider using checkinstall, which provides a clean path for the uninstall.


13.8 Document preparation


13.8.1 roff typesetting

Traditionally, roff is the main Unix text processing system.

See roff(7), groff(7), groff(1), grotty(1), troff(1), groff_mdoc(7), groff_man(7), groff_ms(7), groff_me(7), groff_mm(7), and info groff.

A good tutorial on -me macros exists. If you have groff (1.18 or newer), find /usr/share/doc/groff/meintro.me.gz and do the following:

     $ zcat /usr/share/doc/groff/meintro.me.gz | \
          groff -Tascii -me - | less -R

The following will make a completely plain text file:

     $ zcat /usr/share/doc/groff/meintro.me.gz | \
         GROFF_NO_SGR=1 groff -Tascii -me - | col -b -x > meintro.txt

For printing, use PostScript output.

     $ groff -Tps meintro.txt | lpr
     $ groff -Tps meintro.txt | mpage -2 | lpr

13.8.2 SGML

Preparation:

     # apt-get install debiandoc-sgml debiandoc-sgml-doc

References for debiandoc-sgml:

SGML enables management of multiple formats of a document. One easy SGML system is Debiandoc, which is used here. This requires minor conversion from original text files for the following characters:

To mark a section as a nonprintable comment, enter:

     <!-- State issue here ... -->

To mark a section with a switchable comment, enter:

     <![ %FIXME; [ State issue here ... ]]>

In SGML, the first definition of an entity wins. For example:

     <!entity % qref "INCLUDE">
     <![ %qref; [ <!entity param "Data 1"> ]]>
     <!entity param "Data 2">
     &param;

This ends up as "Data 1". If the first line has "IGNORE" instead of "INCLUDE", this ends up as "Data 2" (the second line is a conditional statement). Also, repeating phrases can be defined in advance separately from the context.

     <!entity whoisthis "my">
     Hello &whoisthis; friend.
     This is &whoisthis; book.

This results in the following:

     Hello my friend.
     This is my book.

See the short SGML example sample.sgml in the examples.

When SGML documents become bigger, sometimes TeX which is used as the backend text processor may cause errors. See TeX/LaTeX, 第 13.8.3 節.


13.8.3 TeX/LaTeX

準備:

     # tasksel # Miscellaneous を選択  --> TeX/LaTeX environment

LaTeX リファレンス:

This is the most powerful typesetting environment. Many SGML processors use this as their back end text processor. Lyx provided by lyx, lyx-xforms, or lyx-qt package offers nice WYSIWYG editing environment for LaTeX while many use Emacs and Vim as the choice for the source editor.

There are many online resources available:

When documents become bigger, sometimes TeX may cause errors. You must increase pool size in /etc/texmf/texmf.cnf (or more appropriately edit /etc/texmf/texmf.d/95NonPath and run update-texmf) to fix this.


13.8.4 Literate Programming

Instead of writing code containing documentation, the literate programmer writes documentation containing code. This approach ensures a good documentation for a program.

For more on literate-programming, see Literate Programming.


13.8.4.1 Noweb

Preparation:

     # apt-get install nowebm

References for Noweb:

This is a WEB-like literate-programming tool which is simpler while providing extensibility and language-independence. [59] When noweb is invoked, it writes the program source code to the output files mentioned in the noweb file, and it writes a TeX file for typeset documentation.

The Debian ifupdown package is a fine example.

     $ apt-get source ifupdown
     $ cd ifupdown*
     $ make ifupdown.pdf ifupdown.ps

13.8.4.2 Doxygen

Preparation:

     # apt-get install doxygen doxygen-doc doxygen-gui

References for Doxygen (created by doxygen!):

It can generate HTML, RTF, Unix manual pages, PostScript, and PDF (using LaTeX) documentation for C++, C, Java, IDL and to some extent PHP and C# programs. Doxygen is compatible to JavaDoc (1.1), Qt-Doc, KDOC and was specifically designed to be used for projects that make use of Troll Tech's Qt toolkit. It creates include dependency graphs, collaboration diagrams, and graphical class hierarchy graphs even for not documented programs. The output is similar to Qt's documentation.


13.9 Packaging

Preparation:

     # apt-get install debian-policy developers-reference \
                       maint-guide dh-make debhelper
     # apt-get install packaging-manual # if Potato

References for packaging:


13.9.1 Packaging a single binary

Quick-and-dirty method to Package a single binary per Joey Hess.

     # mkdir -p mypkg/usr/bin mypkg/DEBIAN
     # cp binary mypkg/usr/bin
     # cat > mypkg/DEBIAN/control
     Package: mypackage
     Version: 1
     Architecture: i386
     Maintainer: Joey Hess <joeyh@debian.org>
     Description: my little package
      Don't expect much.
     ^D
     # dpkg-deb -b mypkg

13.9.2 Packaging with tools

Use dh_make from the dh-make package to create a baseline package. Then, proceed according to instructions in dh-make(1). This uses debhelper in debian/rules.

An older approach is to use deb-make from the debmake package. This uses no debhelper scripts and depends only on the shell.

For examples of multiple-source packages, see "mc" (dpkg-source -x mc_4.5.54.dsc), which uses "sys-build.mk" by Adam Heath (doogie@debian.org), and "glibc" (dpkg-source -x glibc_2.2.4-1.dsc), which uses another system by the late Joel Klecker (espy@debian.org).


[ 前のページ ] [ 目次 ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ 14 ] [ 15 ] [ A ] [ 次のページ ]

Debian レファレンス

1.07-1, 2004年 3月 7日 日曜日 15時48分58秒 UTC時間

Osamu Aoki (青木 修) osamu@debian.org
翻訳: 角田 慎一 tsuno@ngy.1st.ne.jp
著者, 第 A.1 節