Bab 12. Pemrograman

Daftar Isi

12.1. Skrip shell
12.1.1. Kompatibilitas shell POSIX
12.1.2. Parameter shell
12.1.3. Kondisional Shell
12.1.4. Loop shell
12.1.5. Variabel lingkungan shell
12.1.6. Urutan pemrosesan baris perintah shell
12.1.7. Program utilitas untuk skrip shell
12.2. Scripting in interpreted languages
12.2.1. Debugging interpreted language codes
12.2.2. Program GUI dengan skrip shell
12.2.3. Tindakan ubahan untuk filer GUI
12.2.4. Kegilaan skrip pendek Perl
12.3. Menuis kode dalam bahasa yang dikompilasi
12.3.1. C
12.3.2. Program C Sederhana (gcc)
12.3.3. Flex - Lex yang lebih baik
12.3.4. Bison - Yacc yang lebih baik
12.4. Alat analisis kode statis
12.5. Awakutu
12.5.1. Eksekusi gdb dasar
12.5.2. Debugging paket Debian
12.5.3. Mendapatkan backtrace
12.5.4. Perintah gdb tingkat lanjut
12.5.5. Periksa ketergantungan pada pustaka
12.5.6. Alat pelacakan panggilan dinamis
12.5.7. Debugging X Errors
12.5.8. Alat deteksi kebocoran memori
12.5.9. Disassembly biner
12.6. Alat build
12.6.1. Make
12.6.2. Autotools
12.6.2.1. Mengkompilasi dan menginstal program
12.6.2.2. Menghapus instalasi program
12.6.3. Meson
12.7. Web
12.8. Terjemahan kode sumber
12.9. Membuat paket Debian

Saya memberikan beberapa petunjuk bagi orang untuk belajar pemrograman pada sistem Debian yang cukup untuk melacak kode sumber yang dikemas. Berikut adalah paket penting dan paket dokumentasi yang sesuai untuk pemrograman.

Referensi daring tersedia dengan mengetik "man nama" setelah memasang paket manpages dan manpages-dev. Referensi daring untuk alat GNU tersedia dengan mengetik "info nama_program" setelah memasang paket dokumentasi yang bersangkutan. Anda mungkin perlu memasukkan arsip contrib dan non-free selain arsip main karena beberapa dokumentasi GFDL tidak dianggap sesuai dengan DFSG.

Harap pertimbangkan untuk menggunakan alat sistem kontrol versi. Lihat Bagian 10.5, “Git”.

[Awas] Awas

Jangan gunakan "test" sebagai nama berkas uji yang dapat dieksekusi. "test" adalah shell builtin.

[Perhatian] Perhatian

Anda harus memasang program perangkat lunak yang langsung dikompilasi dari sumber ke "/usr/local" atau "/opt" untuk menghindari tabrakan dengan program sistem.

[Tip] Tip

Contoh kode untuk membuat "Song 99 Bottles of Beer" mestinya memberi Anda ide bagus tentang hampir semua bahasa pemrograman.

Skrip shell adalah berkas teks dengan bit eksekusi yang dihidupkan dan berisi perintah dalam format berikut.

#!/bin/sh
 ... command lines

Baris pertama menentukan interpreter shell yang membaca dan mengeksekusi isi berkas ini.

Membaca skrip shell adalah cara terbaik untuk memahami cara kerja sistem seperti Unix. Di sini, saya memberikan beberapa petunjuk dan pengingat untuk pemrograman shell. Lihat "Kesalahan Shell" (http://www.greenend.org.uk/rjk/2001/04/shell.html) untuk belajar dari kesalahan.

Tidak seperti mode interaktif shell (lihat Bagian 1.5, “Perintah shell sederhana” dan Bagian 1.6, “Pemrosesan teks mirip Unix”), skrip shell sering menggunakan parameter, kondisional, dan loop.

Setiap perintah mengembalikan status keluar yang dapat digunakan untuk ekspresi bersyarat.

  • Sukses: 0 ("Benar/True")

  • Galat: bukan 0 ("Salah/False")

[Catatan] Catatan

"0" dalam konteks kondisional shell berarti "Benar", sedangkan "0" dalam konteks kondisional C berarti "Salah".

[Catatan] Catatan

"[" adalah setara dengan perintah test, yang mengevaluasi argumennya sampai "]" sebagai ekspresi bersyarat.

Idiom kondisionak dasar untuk diingat adalah sebagai berikut.

  • perintah && bila_sukses_jalankan_perintah_ini_juga || true"

  • "perintah || bila_tidak_sukses_jalankan_perintah_ini_juga || true"

  • Cuplikan skrip multi-baris sebagai berikut

if [ conditional_expression ]; then
 if_success_run_this_command
else
 if_not_success_run_this_command
fi

Di sini "|| true" di akhir diperlukan untuk memastikan skrip shell ini tidak keluar pada baris ini secara tidak sengaja ketika shell dipanggil dengan flag"-e".



Operator perbandingan integer aritmatika dalam ekspresi bersyarat adalah "-eq", "-ne", "-lt", "-le", "-gt", dan "-ge".

Shell memproses skrip kira-kira sebagai urutan berikut.

  • Shell membaca satu baris.

  • Shell mengelompokkan bagian dari baris sebagai satu token jika berada di dalam "…" atau '…'.

  • Shell memecah bagian lain dari suatu baris menjadi token dengan yang berikut.

    • Ruang kosong: spasi tab ganti baris

    • Karakter meta: | ; & ( )

  • Shell memeriksa kata tetapan untuk setiap token untuk menyesuaikan perilakunya jika tidak dalam "…" atau '…'.

    • kata tetapan: if then elif else fi for in while unless do done case esac

  • Shell mengekspansikan alias jika tidak dalam "…" atau '…'.

  • Shell mengekspansikan tilde jika tidak dalam "…" atau '…'.

    • "~" → direktori rumah pengguna saat ini

    • "~~pengguna" → direktori rumah pengguna

  • Shell mengekspansikan parameter ke nilainya jika tidak dalam '…'.

    • parameter: "$PARAMETER" atau "${PARAMETER} "

  • Shell mengekspansikan substitusi perintah jika tidak dalam '…'.

    • "$( command )" → keluaran dari "perintah"

    • "` perintah `" → keluaran dari "perintah"

  • Shell mengekspansikan pathname glob untuk mencocokkan nama berkas jika tidak dalam "…"" atau '…'.

    • * → sebarang karakter

    • ? → satu karakter

    • [...] → salah satu karakter dalam "..."

  • Shell mencari perintah dari yang berikut dan mengeksekusinya.

    • definisi fungsi

    • perintah builtin

    • berkas yang dapat dieksekusi dalam "$PATH"

  • Shell pergi ke baris berikutnya dan mengulangi proses ini lagi dari puncak urutan ini.

Kutip tunggal dalam kutip ganda tidak berpengaruh.

Mengeksekusi "set -x" di shell atau menjalankan shell dengan opsi "-x" membuat shell mencetak semua perintah yang dieksekusi. Ini sangat berguna untuk debugging.


Ketika Anda ingin mengotomatiskan tugas di Debian, Anda harus menulisnya dengan bahasa yang diintepretasi terlebih dahulu. Panduan untuk pilihan bahasa yang diinterpretasi adalah:

  • Gunakan dash, jika tugas sederhana yang menggabungkan program CLI dengan program shell.

  • Gunakan python3, jika tugas tidak sederhana dan Anda menulisnya dari awal.

  • Gunakan perl, tcl, ruby, ... jika sudah ada kode yang menggunakan salah satu bahasa ini di Debian yang perlu disentuh untuk melakukan tugas tersebut.

Jika kode yang dihasilkan terlalu lambat, Anda dapat menulis ulang hanya bagian penting untuk kecepatan eksekusi dalam bahasa yang dikompilasi dan memanggilnya dari bahasa yang ditafsirkan.

Skrip shell dapat diperbaiki untuk membuat program GUI yang menarik. Caranya adalah dengan menggunakan salah satu program dialog yang disebut alih-alih interaksi membosankan menggunakan perintah echo dan read.


Berikut adalah contoh program GUI untuk menunjukkan betapa mudahnya itu hanya dengan suatu skrip shell.

Skrip ini menggunakan zenity untuk memilih berkas (baku /etc/motd) dan menampilkannya.

Peluncur GUI untuk skrip ini dapat dibuat berikut Bagian 9.4.10, “Memulai program dari GUI”.

#!/bin/sh -e
# Copyright (C) 2021 Osamu Aoki <osamu@debian.org>, Public Domain
# vim:set sw=2 sts=2 et:
DATA_FILE=$(zenity --file-selection --filename="/etc/motd" --title="Select a file to check") || \
  ( echo "E: File selection error" >&2 ; exit 1 )
# Check size of archive
if ( file -ib "$DATA_FILE" | grep -qe '^text/' ) ; then
  zenity --info --title="Check file: $DATA_FILE" --width 640  --height 400 \
    --text="$(head -n 20 "$DATA_FILE")"
else
  zenity --info --title="Check file: $DATA_FILE" --width 640  --height 400 \
    --text="The data is MIME=$(file -ib "$DATA_FILE")"
fi

Pendekatan semacam ini untuk program GUI dengan skrip shell hanya berguna untuk kasus pilihan sederhana. Jika Anda ingin menulis program apa pun dengan kompleksitas, silakan pertimbangkan untuk menulisnya di platform yang lebih mampu.


Di sini, Bagian 12.3.3, “Flex - Lex yang lebih baik” dan Bagian 12.3.4, “Bison - Yacc yang lebih baik” disertakan untuk menunjukkan bagaimana program seperti kompiler dapat ditulis dalam bahasa C dengan menyusun deskripsi tingkat yang lebih tinggi ke dalam bahasa C.

Anda dapat mengatur lingkungan yang tepat untuk mengkompilasi program yang ditulis dalam bahasa pemrograman C dengan yang berikut.

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

Paket libc6-dev, yaitu Pustaka GNU C, menyediakan pustaka standar C yang merupakan kumpulan berkas header dan pustaka fungsi yang digunakan oleh bahasa pemrograman C.

Lihat referensi untuk C dengan cara berikut.

  • "info libc" (referensi fungsi pustaka C)

  • gcc(1) dan "info gcc"

  • each_C_library_function_name(3)

  • Kernighan & Ritchie, "The C Programming Language", 2nd edition (Prentice Hall)

Flex adalah generator analisis leksikal cepat yang kompatibel dengan Lex.

Tutorial untuk flex(1) dapat ditemukan di "info flex".

You need to provide your own "main()" and "yywrap()". Otherwise, your flex program should look like this to compile without a library. This is because that "yywrap" is a macro and "%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(1) command line (like AT&T-Lex with "-ll"). No "%option" is needed in this case.

Lint like tools can help automatic static code analysis.

Indent like tools can help human code reviews by reformatting source codes consistently.

Ctags like tools can help human code reviews by generating an index (or tag) file of names found in source codes.

[Tip] Tip

Configuring your favorite editor (emacs or vim) to use asynchronous lint engine plugins helps your code writing. These plugins are getting very powerful by taking advantage of Language Server Protocol. Since they are moving fast, using their upstream code instead of Debian package may be a good option.


Debug is important part of programming activities. Knowing how to debug programs makes you a good Debian user who can produce meaningful bug reports.


Primary debugger on Debian is gdb(1) which enables you to inspect a program while it executes.

Let's install gdb and related programs by the following.

# apt-get install gdb gdb-doc build-essential devscripts

Good tutorial of gdb can be found:

  • info gdb

  • "Debugging dengan GDB" di /usr/share/doc/gdb-doc/html/gdb/index.html

  • tutorial di web

Here is a simple example of using gdb(1) on a "program" compiled with the "-g" option to produce debugging information.

$ gdb program
(gdb) b 1                # set break point at line 1
(gdb) run args           # run program with args
(gdb) next               # next line
...
(gdb) step               # step forward
...
(gdb) p parm             # print parm
...
(gdb) p parm=12          # set value to 12
...
(gdb) quit
[Tip] Tip

Many gdb(1) commands can be abbreviated. Tab expansion works as in the shell.

Karena semua biner yang dipasang harus di-strip pada sistem Debian secara baku, sebagian besar simbol debug dihapus dalam paket normal. Untuk men-debug paket Debian dengan gdb(1), paket *-dbgsym perlu dipasang (misalnya coreutils-dbgsym dalam kasus coreutils). Paket sumber menghasilkan paket *-dbgsym secara otomatis bersama dengan paket biner normal dan paket debug tersebut ditempatkan secara terpisah dalam arsip debian-debug. Silakan merujuk ke artikel di Debian Wiki untuk informasi lebih lanjut.

Jika paket yang akan di-debug tidak menyediakan paket *-dbgsym, Anda perlu memasangnya setelah membangun kembali dengan yang berikut.

$ mkdir /path/new ; cd /path/new
$ sudo apt-get update
$ sudo apt-get dist-upgrade
$ sudo apt-get install fakeroot devscripts build-essential
$ apt-get source package_name
$ cd package_name*
$ sudo apt-get build-dep ./

Perbaiki bug jika diperlukan.

Bump package version to one which does not collide with official Debian versions, e.g. one appended with "+debug1" when recompiling existing package version, or one appended with "~pre1" when compiling unreleased package version by the following.

$ dch -i

Kompilasi dan instal paket beserta simbol debug dengan yang berikut ini.

$ export DEB_BUILD_OPTIONS="nostrip noopt"
$ debuild
$ cd ..
$ sudo debi package_name*.changes

Anda perlu memeriksa skrip build paket dan memastikan menggunakan "CFLAGS = -g -Wall" untuk mengkompilasi biner.

When you encounter program crash, reporting bug report with cut-and-pasted backtrace information is a good idea.

Backtrace dapat diperoleh dengan gdb(1) menggunakan salah satu pendekatan berikut:

Untuk pengulangan tak hingga atau situasi papan ketik beku, Anda dapat memaksa untuk program crash dengan menekan Ctrl-\ atau Ctrl-C atau mengeksekusi"kill -ABRT PID ". (Lihat Bagian 9.4.12, “Membunuh sebuah proses”)

[Tip] Tip

Often, you see a backtrace where one or more of the top lines are in "malloc()" or "g_malloc()". When this happens, chances are your backtrace isn't very useful. The easiest way to find some useful information is to set the environment variable "$MALLOC_CHECK_" to a value of 2 (malloc(3)). You can do this while running gdb by doing the following.

 $ MALLOC_CHECK_=2 gdb hello

Make is a utility to maintain groups of programs. Upon execution of make(1), make read the rule file, "Makefile", and updates a target if it depends on prerequisite files that have been modified since the target was last modified, or if the target does not exist. The execution of these updates may occur concurrently.

Sintaks berkas aturan adalah sebagai berikut.

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, by the following.

%.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.



Jalankan "make -p -f/dev/null" untuk melihat aturan internal otomatis.

Autotools adalah keluarga alat pemrograman yang dirancang untuk membantu dalam membuat paket kode sumber portabel ke banyak sistem mirip Unix.

  • Autoconf is a tool to produce a shell script "configure" from "configure.ac".

    • "configure" is used later to produce "Makefile" from "Makefile.in" template.

  • Automake is a tool to produce "Makefile.in" from "Makefile.am".

  • Libtool is a shell script to address the software portability problem when compiling shared libraries from source code.

The software build system has been evolving:

  • Autotools on the top of Make has been the de facto standard for the portable build infrastructure since 1990s. This is extremely slow.

  • CMake initially released in 2000 improved speed significantly but was still build on the top of inherently slow Make.

  • Ninja initially released in 2012 is meant to replace Make for the further improved build speed but is also designed to have its input files generated by a higher-level build system.

  • Meson initially released in 2013 is the new popular and fast higher-level build system which uses Ninja as its backend.

Lihat dokumen yang ditemukan di "The Meson Build system" dan "The Ninja build system".

Basic interactive dynamic web pages can be made as follows.

  • Kueri disajikan kepada pengguna peramban menggunakan formulir HTML.

  • Filling and clicking on the form entries sends one of the following URL string with encoded parameters from the browser to the web server.

    • "http://www.foo.dom/cgi-bin/program.pl?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"

    • "http://www.foo.dom/cgi-bin/program.py?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"

    • "http://www.foo.dom/program.php?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"

  • " %nn" dalam URL diganti dengan sebuah karakter dengan nilai heksadesimal nn.

  • The environment variable is set as: "QUERY_STRING="VAR1=VAL1 VAR2=VAL2 VAR3=VAL3"".

  • CGI program (any one of "program.*") on the web server executes itself with the environment variable "$QUERY_STRING".

  • stdout of CGI program is sent to the web browser and is presented as an interactive dynamic web page.

For security reasons it is better not to hand craft new hacks for parsing CGI parameters. There are established modules for them in Perl and Python. PHP comes with these functionalities. When client data storage is needed, HTTP cookies are used. When client side data processing is needed, Javascript is frequently used.

Untuk informasi lebih lanjut, lihat Common Gateway Interface, The Apache Software Foundation, dan JavaScript.

Searching "CGI tutorial" on Google by typing encoded URL http://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial directly to the browser address is a good way to see the CGI script in action on the Google server.

Jika Anda ingin membuat paket Debian, baca berikut ini.

Ada paket seperti debmake, dh-make, dh-make-perl, dll., yang membantu pengemasan.