One place for hosting & domains

      How To Write Unit Tests in Go


      The author selected the FreeBSD Foundation to receive a donation as part of the Write for DOnations program.

      Introduction

      A unit test is a function that tests a specific piece of code from a program or package. The job of unit tests is to check the correctness of an application, and they are a crucial part of the Go programming language.

      In this tutorial, you will create a small program and then run a series of tests on your code using Go’s testing package and the go test command. Once you complete the tutorial, you will have a working unit-testing suite that includes a table-based unit test, a coverage test, a benchmark, and a documented example.

      Prerequisites

      To complete this tutorial, you’ll need the following:

      Note: This tutorial uses Go Modules, which is a package management system introduced in Go version 1.11. Go Modules are intended to replace the $GOPATH and became the default option starting with Go version 1.13. For a more comprehensive overview of the differences between Go Modules and the $GOPATH, consider reading this official blog post from the Go core team.

      This tutorial was tested using Go version 1.14

      Step 1 — Creating a Sample Program to Unit Test

      Before you can write any unit tests, you need some code for your tests to analyze. In this step, you will build a small program that sums two integers. In the subsequent steps, you will use go test to test the program.

      First, create a new directory called math:

      Move inside the new directory:

      This will be the root directory for your program, and you will run all remaining commands from here.

      Now, using nano or your preferred text editor, create a new file called math.go:

      Add the following code:

      ./math/math.go

      package math
      
      // Add is our function that sums two integers
      func Add(x, y int) (res int) {
          return x + y
      }
      
      // Subtract subtracts two integers
      func Subtract(x, y int) (res int) {
          return x - y
      }
      

      Here you are creating two functions called Add and Subtract. Each function accepts two integers and returns either their sum (func Add) or their difference (func Subtract).

      Save and close the file.

      In this step, you wrote some code in Go. Now, in the following steps, you will write some unit tests to ensure that your code functions properly.

      Step 2 — Writing Unit Tests in Go

      In this step, you will write your first test in Go. Writing tests in Go requires a test file link, and this test file must always end with _test.go. By convention, Go testing files are always located in the same folder, or package, where the code they are testing resides. These files are not built by the compiler when you run the go build command, so you needn’t worry about them ending up in deployments.

      And as with everything in Go, the language is opinionated about testing. The Go language provides a minimal yet complete package called testing that developers use alongside the go test command. The testing package provides some useful conventions, such as coverage tests and benchmarks, which you will now explore.

      Use your editor to create and open a new file called math_test.go:

      A test function in Go includes this signature: func TestXxxx(t *testing.T). This means that all test functions must start with the word Test, followed by a suffix whose first word is capitalized. Test functions in Go receive only one parameter, and in this case, it’s a pointer of type testing.T. This type contains useful methods that you will need to output results, log errors to the screen, and signal failures, like the t.Errorf() method.

      Add the following code to math_test.go:

      ./math/math_test.go

      
      package math
      
      import "testing"
      
      func TestAdd(t *testing.T){
      
          got := Add(4, 6)
          want := 10
      
          if got != want {
              t.Errorf("got %q, wanted %q", got, want)
          }
      }
      

      First, you declare the name of the package that you want to test—math. Then you import the testing package itself, which then makes available the testing.T type and the other types and methods exported by the package. The code and testing logic is contained in the TestAdd function.

      To summarize, the following are characteristics of a test in Go:

      • The first and only parameter must be t *testing.T
      • The testing function begins with the word Test followed by a word or phrase that starts with a capital letter (the convention is to use the name of the method under test, e.g., TestAdd)
      • The test calls t.Error or t.Fail to indicate a failure (you are calling t.Error because it returns more detail than t.Fail)
      • You can use t.Log to provide non-failing debug information
      • Tests are saved in files using this naming convention: foo_test.go, such as math_test.go.

      Save and then close the file.

      In this step, you wrote your first test in Go. In the next step, you will begin using go test to test your code.

      Step 3 — Testing Your Go Code Using the go test command

      In this step, you will test your code. go test is a powerful subcommand that helps you automate your tests. go test accepts different flags that can configure the tests you wish to run, how much verbosity the tests return, and more.

      From your project’s root directory, run your first test:

      You will receive the following output:

      Output

      PASS ok ./math 0.988s

      PASS means the code is working as expected. When a test fails, you will see FAIL.

      The go test subcommand only looks for files with the _test.go suffix. go test then scans those file(s) for special functions including func TestXxx and several others that we will cover in later steps. go test then generates a temporary main package that calls these functions in the proper way, builds and runs them, reports the results, and finally cleans everything up.

      Our go test is probably sufficient for our little program, but there will be times when you’ll wish to see what tests are running and how long each takes. Adding the -v flag increases verbosity. Rerun your test with the new flag:

      You will see the following output:

      Output

      === RUN TestAdd --- PASS: TestAdd (0.00s) PASS ok ./math 1.410s

      In this step, you ran a basic unit test using the go test subcommand. In the next step, you will write a more complex, table-driven unit test.

      Step 4 — Writing Table-Driven Tests in Go

      A table-driven test is like a basic unit test except that it maintains a table of different values and results. The testing suite iterates over these values and submits them to the test code. Using this approach, we get to test several combinations of inputs and their respective output.

      You will now replace your unit test with a table of structs, whose fields include the necessary two arguments (two integers) and the expected result (their sum) for your Add function.

      Reopen math_test.go:

      Delete all the code in the file and add the following table-driven unit test instead:

      ./math/math_test.go

      
      package math
      
      import "testing"
      
      // arg1 means argument 1 and arg2 means argument 2, and the expected stands for the 'result we expect'
      type addTest struct {
          arg1, arg2, expected int
      }
      
      var addTests = []addTest{
          addTest{2, 3, 5},
          addTest{4, 8, 12},
          addTest{6, 9, 15},
          addTest{3, 10, 13},
      
      }
      
      
      func TestAdd(t *testing.T){
      
          for _, test := range addTests{
              if output := Add(test.arg1, test.arg2); output != test.expected {
                  t.Errorf("Output %q not equal to expected %q", output, test.expected)
              }
          }
      }
      
      

      Here you are defining a struct, populating a table of structs that include the arguments and expected results for your Add function, and then writing a new TestAdd function. In this new function, you iterate over the table, run the arguments, compare the outputs to each expected result, and then returning any errors, should they occur.

      Save and close the file.

      Now run the test with the -v flag:

      You will see the same output as before:

      Output

      === RUN TestAdd --- PASS: TestAdd (0.00s) PASS ok ./math 1.712s

      With each iteration of the loop, the code tests the value calculated by the Add function against an expected value.

      In this step, you wrote a table-driven test. In the next step, you will write a coverage test instead.

      Step 5 — Writing Coverage Tests in Go

      In this step, you will write a coverage test in Go. When writing tests, it is often important to know how much of your actual code the tests cover. This is generally referred to as coverage. This is also why you have not written a test for your Subtract function — so we can view an incomplete coverage test.

      Run the following command to calculate the coverage for your current unit test:

      • go test -coverprofile=coverage.out

      You will receive the following output:

      Output

      PASS coverage: 50.0% of statements ok ./math 2.073s

      Go saved this coverage data in the file coverage.out. Now you can present the results in a web browser.

      Run the following command:

      • go tool cover -html=coverage.out

      A web browser will open, and your results will render:

      go unit testing coverage.out

      The green text indicates coverage, whereas the red text indicates the opposite.

      In this step, you tested the coverage of your table-driven unit test. In the next step, you will benchmark your function.

      Step 6 — Writing Benchmarks in Go

      In this step, you will write a benchmark test in Go. Benchmarking measures the performance of a function or program. This allows you to compare implementations and to understand the impact of the changes you make to your code. Using that information, you can reveal parts of your Go source code worth optimizing.

      In Go, functions that take the form func BenchmarkXxx(*testing.B) are considered benchmarks. go test will execute these benchmarks when you provide the -bench flag. Benchmarks are run sequentially.

      Let’s add a benchmark to our unit test.

      Open math_test.go:

      Now add a benchamrk function using the func BenchmarkXxx(*testing.B) syntax:

      ./math_test.go

      ...
      func BenchmarkAdd(b *testing.B){
          for i :=0; i < b.N ; i++{
              Add(4, 6)
          }
      }
      

      The benchmark function must run the target code b.N times, where N is an integer that can be adjusted. During benchmark execution, b.N is adjusted until the benchmark function lasts long enough to be timed reliably. The --bench flag accepts its arguments in the form of a regular expression.

      Save and close the file.

      Now let’s use go test again to run our benchmark:

      The . will match every benchmark function in a file.

      You can also declare benchmark functions explicitly:

      Run either command, and you will see an output like this:

      Output

      goos: windows goarch: amd64 pkg: math BenchmarkAdd-4 1000000000 1.07 ns/op PASS ok ./math 2.074s

      The resulting output means that the loop ran 10,000,000 times at a speed of 1.07 nanosecond per loop.

      Note: Try not to benchmark your Go code on a busy system being used for other purposes, or else you will interfere with the benchmarking process and get inaccurate results

      You have now added a benchmark to your growing unit test. In the next and final step, you will add examples to your documentation, which go test will also evaluate.

      Step 7 — Documenting Your Go Code with Examples

      In this step, you will document your Go code with examples and then test those examples. Go is very focused on proper documentation, and example code adds another dimension both to documentation and testing. Examples are based on existing methods and functions. Your examples should show users how to use a specific piece of code. Example functions are the third type of function treated specially by the go test subcommand.

      To begin, reopen math_test.go,

      Now add the highlighted code. This will add the fmt package to the import list and your example function at the end of the file:

      ./math/math_test.go

      
      package math
      
      import (
          "fmt"
          "testing"
      )
      
      // arg1 means argument 1 and arg2 means argument 2, and the expected stands for the 'result we expect'
      type addTest struct {
          arg1, arg2, expected int
      }
      
      var addTests = []addTest{
          addTest{2, 3, 5},
          addTest{4, 8, 12},
          addTest{6, 9, 15},
          addTest{3, 10, 13},
      }
      
      func TestAdd(t *testing.T) {
      
          for _, test := range addTests {
              if output := Add(test.arg1, test.arg2); output != test.expected {
                  t.Errorf("Output %q not equal to expected %q", output, test.expected)
              }
          }
      }
      
      func BenchmarkAdd(b *testing.B) {
          for i := 0; i < b.N; i++ {
              Add(4, 6)
          }
      }
      
      
      func ExampleAdd() {
          fmt.Println(Add(4, 6))
          // Output: 10
      }
      
      

      The Output: line is used to specify and document the expected output.

      Note: The comparison ignores leading and trailing space.

      Save and close the file.

      Now rerun your unit test:

      You will see an updated outout like this:

      Output

      === RUN TestAdd --- PASS: TestAdd (0.00s) === RUN ExampleAdd --- PASS: ExampleAdd (0.00s) PASS ok ./math 0.442s

      Your examples are now also tested. This feature improves your documentation and also makes your unit test more robust.

      Conclusion

      In this tutorial, you created a small program and then wrote a basic unit test to check its functionality. You then rewrote your unit test as a table-based unit test and then added a coverage test, a benchmark, and a documented example.

      Taking time to write adequate unit tests is useful to you as a programmer because it improves your confidence that the code or program you have written will continue to work as expected. The testing package in Go provides you with considerable unit-testing capabilities. To learn more, refer to Go’s official documentation.

      And if you wish to learn more about programming in Go, visit our tutorial series / free ebook, How To Code in Go.



      Source link

      Cara Menggunakan Systemctl untuk Mengelola Layanan dan Unit Systemd


      Pengantar

      Systemd adalah sistem init dan pengelola sistem yang secara luas telah menjadi standar baru untuk berbagai distribusi Linux. Karena digunakan secara luas, memahami systemd akan mengatasi banyak masalah, karena ini akan membuat pengelolaan server menjadi jauh lebih mudah. Mempelajari dan memanfaatkan berbagai alat dan daemon yang meliputi systemd akan membantu Anda menghargai kehebatan, fleksibilitas, dan kemampuan yang diberikannya dengan lebih baik, atau setidaknya membantu Anda melakukan pekerjaan tanpa banyak kesulitan.

      Dalam panduan ini, kita akan membahas perintah systemctl, yang merupakan alat manajemen pusat untuk mengontrol sistem init. Kita akan membahas cara mengelola layanan, memeriksa status, mengubah keadaan sistem, dan menangani berkas konfigurasi.

      Harap diperhatikan bahwa meskipun systemd telah menjadi sistem init asali untuk banyak distribusi Linux, tetapi tidak diterapkan secara universal ke semua distribusi. Saat mengikuti tutorial ini, jika terminal Anda memberikan keluaran pesan kesalahan bash: systemctl is not installed, kemungkinan mesin Anda menginstal sistem init yang berbeda.

      Manajemen Layanan

      Kegunaan mendasar dari sistem init adalah menginisialisasi komponen yang harus dimulai setelah kernel Linux melakukan boot (biasanya dikenal dengan komponen “userland”). Sistem init juga digunakan untuk mengelola layanan dan daemon bagi server di titik apa pun selama sistem dijalankan. Dengan mengingat hal itu, kita akan mulai dengan beberapa operasi manajemen layanan dasar.

      Di systemd, target sebagian besar tindakan adalah “unit”, yakni sumber daya yang diketahui cara pengelolaannya oleh systemd. Unit dikelompokkan menurut tipe sumber daya yang diwakilinya dan didefinisikan bersama berkas yang dikenal dengan berkas unit. Tipe setiap unit dapat ditebak dari akhiran di belakang berkas.

      Untuk tugas manajemen layanan, unit target akan berupa unit layanan, yang memiliki berkas unit dengan akhiran .service. Namun, untuk kebanyakan perintah manajemen layanan, Anda sebenarnya dapat menanggalkan akhiran .service, karena systemd sudah cukup cerdas untuk mengetahui bahwa Anda mungkin ingin mengoperasikan suatu layanan saat menggunakan perintah manajemen layanan.

      Memulai dan Menghentikan Layanan

      Untuk memulai layanan systemd, yang mengeksekusi instruksi dalam berkas unit layanan, gunakan perintah start. Jika menjalankan sebagai pengguna non-root, Anda akan perlu menggunakan sudo karena ini akan memengaruhi keadaan sistem operasi:

      • sudo systemctl start application.service

      Seperti yang kami sebutkan di atas, systemd tahu untuk mencari berkas *.service untuk perintah manajemen layanan, sehingga perintah dapat diketikkan semudah ini:

      • sudo systemctl start application

      Meskipun Anda mungkin menggunakan format di atas untuk administrasi umum, demi kejelasan, kita akan menggunakan akhiran .service untuk perintah selebihnya, agar target operasi kita lebih jelas.

      Untuk menghentikan layanan yang sedang berjalan, Anda dapat menggunakan perintah stop sebagai gantinya:

      • sudo systemctl stop application.service

      Memulai Ulang dan Memuat Ulang

      Untuk memulai ulang layanan yang sedang berjalan, Anda dapat menggunakan perintah restart:

      • sudo systemctl restart application.service

      Jika aplikasi tersebut dapat memuat ulang berkas konfigurasinya (tanpa memulai ulang), Anda dapat memberikan perintah reload untuk memulai proses:

      • sudo systemctl reload application.service

      Jika tidak yakin apakah layanan memiliki fungsionalitas untuk memuat ulang konfigurasinya, Anda dapat memberikan perintah reload-or-restart. Perintah ini akan memuat ulang konfigurasi jika tersedia. Jika tidak, perintah ini akan memulai ulang layanan sehingga konfigurasi baru akan diambil:

      • sudo systemctl reload-or-restart application.service

      Mengaktifkan dan Menonaktifkan Layanan

      Perintah di atas berguna untuk memulai atau menghentikan layanan selama sesi yang berjalan saat ini. Untuk memberi tahu systemd agar memulai layanan secara otomatis saat boot, Anda harus mengaktifkannya.

      Untuk memulai layanan saat boot, gunakan perintah enable:

      • sudo systemctl enable application.service

      Ini akan membuat tautan simbolis dari salinan berkas layanan sistem (biasanya di /lib/systemd/system atau /etc/systemd/system) ke dalam lokasi di diska tempat systemd mencari berkas autostart (biasanya /etc/systemd/system/some_target.target.wants. Kita akan membahas targetnya nanti dalam panduan ini).

      Untuk menonaktifkan layanan agar tidak dimulai secara otomatis, Anda dapat mengetikkan:

      • sudo systemctl disable application.service

      Ini akan menghapus tautan simbolis yang menandakan bahwa layanan harus dimulai secara otomatis.

      Ingatlah bahwa mengaktifkan layanan tidak akan memulainya di sesi saat ini. Jika Anda ingin memulai layanan dan juga mengaktifkannya saat boot, Anda harus memberikan perintah start dan enable.

      Memeriksa Status Layanan

      Untuk memeriksa status layanan di sistem, Anda dapat menggunakan perintah status:

      • systemctl status application.service

      Perintah ini akan memberi tahu Anda keadaan layanan, hierarki cgroup, dan beberapa baris log pertama.

      Misalnya, saat memeriksa status server Nginx, Anda mungkin melihat keluaran seperti ini:

      Output

      ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2015-01-27 19:41:23 EST; 22h ago Main PID: 495 (nginx) CGroup: /system.slice/nginx.service ├─495 nginx: master process /usr/bin/nginx -g pid /run/nginx.pid; error_log stderr; └─496 nginx: worker process Jan 27 19:41:23 desktop systemd[1]: Starting A high performance web server and a reverse proxy server... Jan 27 19:41:23 desktop systemd[1]: Started A high performance web server and a reverse proxy server.

      Ini memberikan gambaran bagus tentang status aplikasi saat ini, yang memberi tahu Anda masalah dan tindakan yang mungkin diperlukan.

      Ada juga metode untuk memeriksa keadaan tertentu. Misalnya, untuk memeriksa agar tahu apakah suatu unit sedang aktif (berjalan), Anda dapat menggunakan perintah is-active:

      • systemctl is-active application.service

      Ini akan menunjukkan keadaan unit saat ini, yang biasanya berupa active atau inactive. Kode yang keluar akan “0” jika aktif, sehingga membuat hasilnya jadi lebih mudah diurai dalam skrip shell.

      Untuk melihat apakah unit diaktifkan, Anda dapat menggunakan perintah is-enabled:

      • systemctl is-enabled application.service

      Ini akan memberikan keluaran apakah layanan enabled atau disabled dan akan menetapkan lagi kode keluar ke “0” atau “1”, tergantung jawaban terhadap pertanyaan perintah.

      Pemeriksaan ketiga adalah apakah unit dalam keadaan gagal. Ini menandakan adanya masalah saat memulai unit tersebut:

      • systemctl is-failed application.service

      Hasilnya akan menjadi active jika berjalan dengan benar atau failed jika terjadi kesalahan. Jika unit sengaja dihentikan, hasilnya mungkin akan berupa unknown atau inactive. Status keluar “0” menandakan terjadi suatu kegagalan dan status keluar “1” menandakan status lainnya.

      Gambaran Umum Keadaan Sistem

      Sejauh ini, perintah berguna untuk mengelola layanan tunggal, tetapi tidak terlalu berguna untuk mempelajari keadaan sistem saat ini. Ada sejumlah sejumlah perintah systemctl yang memberikan informasi ini.

      Menampilkan Daftar Unit Saat Ini

      Untuk melihat daftar semua unit aktif yang diketahui systemd, kita dapat menggunakan perintah list-units:

      Perintah ini akan menampilkan semua unit systemd yang saat ini aktif di sistem. Keluarannya akan terlihat seperti ini:

      Output

      UNIT LOAD ACTIVE SUB DESCRIPTION atd.service loaded active running ATD daemon avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack dbus.service loaded active running D-Bus System Message Bus dcron.service loaded active running Periodic Command Scheduler dkms.service loaded active exited Dynamic Kernel Modules System getty@tty1.service loaded active running Getty on tty1 . . .

      Keluarannya memiliki kolom berikut:

      • UNIT: Nama unit systemd
      • LOAD: Apakah konfigurasi unit telah diurai oleh systemd. Konfigurasi unit yang dimuat tersimpan dalam memori.
      • ACTIVE: Ringkasan keadaan apakah unit aktif. Ini biasanya cara yang cukup mendasar untuk mengetahui apakah unit berhasil dimulai atau tidak.
      • SUB: Ini tingkat keadaan lebih rendah yang menunjukkan informasi lebih detail tentang unit. Ini seringkali bervariasi menurut tipe unit, keadaan, dan metode aktual unit yang dijalankan.
      • DESCRIPTION: Deskripsi teks singkat tentang apa yang dilakukan unit.

      Karena perintah list-units hanya menampilkan unit aktif secara asali, semua entri di atas akan menampilkan loaded dalam kolom LOAD dan active dalam kolom ACTIVE. Tampilan ini sebenarnya adalah perilaku asali systemctl bila dipanggil tanpa perintah tambahan, sehingga Anda akan melihat hal yang sama jika memanggil systemctl tanpa argumen:

      Kita dapat menyuruh systemctl agar mengeluarkan informasi yang berbeda dengan memberikan bendera tambahan. Misalnya, untuk melihat semua unit yang telah dimuat (atau berupaya dimuat) oleh systemd , entah saat ini aktif atau tidak, Anda dapat menggunakan bendera --all, seperti ini:

      • systemctl list-units --all

      Ini akan menampilkan unit yang telah dimuat atau berupaya dimuat oleh systemd, terlepas dari keadaannya saat ini di sistem. Beberapa unit menjadi tidak aktif setelah berjalan, dan beberapa unit yang berupaya dimuat oleh systemd mungkin tidak ditemukan pada diska.

      Anda dapat menggunakan bendera lain untuk menyaring hasil ini. Misalnya, kita dapat menggunakan bendera --state= untuk menandai keadaan LOAD, ACTIVE, atau SUB yang ingin kita lihat. Anda harus mempertahankan bendera --all agar systemctl mengizinkan unit nonaktif untuk ditampilkan:

      • systemctl list-units --all --state=inactive

      Filter umum lainnya adalah filter --type=. Kita dapat menyuruh systemctl agar hanya menampilkan unit dengan tipe yang kita minati. Misalnya, untuk melihat unit layanan aktif saja, kita dapat menggunakan:

      • systemctl list-units --type=service

      Menampilkan Daftar Semua Berkas Unit

      Perintah list-units hanya menampilkan unit yang telah berupaya diurai dan dimuat systemd ke dalam memori. Karena systemd hanya akan membaca unit yang dianggapnya perlu, maka tidak perlu menyertakan semua unit yang tersedia di sistem. Untuk melihat setiap berkas unit yang tersedia dalam jalur systemd, termasuk berkas yang tidak berupaya dimuat oleh systemd, Anda dapat menggunakan perintah list-unit-files sebagai gantinya:

      • systemctl list-unit-files

      Unit adalah representasi dari sumber daya yang diketahui systemd. Karena systemd menganggap belum perlu membaca semua definisi unit di tampilan ini, systemd hanya menampilkan informasi tentang berkas itu saja. Keluarannya memiliki dua kolom: berkas unit dan keadaan.

      Output

      UNIT FILE STATE proc-sys-fs-binfmt_misc.automount static dev-hugepages.mount static dev-mqueue.mount static proc-fs-nfsd.mount static proc-sys-fs-binfmt_misc.mount static sys-fs-fuse-connections.mount static sys-kernel-config.mount static sys-kernel-debug.mount static tmp.mount static var-lib-nfs-rpc_pipefs.mount static org.cups.cupsd.path enabled . . .

      Keadaan biasanya berupa enabled, disabled, static, atau masked. Dalam konteks ini, static berarti berkas unit tidak berisi bagian install, yang digunakan untuk mengaktifkan unit. Dengan demikian, unit-unit ini tidak dapat diaktifkan. Biasanya, ini berarti unit melakukan tindakan sekali-jalan atau hanya digunakan sebagai dependensi unit lain dan tidak boleh dijalankan dengan sendirinya.

      Kita akan membahas makna masked sebentar lagi.

      Manajemen Unit

      Sejauh ini, kita telah menggunakan beberapa layanan dan menampilkan informasi tentang unit dan berkas unit yang diketahui oleh systemd. Namun, kita dapat mengetahui informasi yang lebih spesifik tentang unit menggunakan beberapa perintah tambahan.

      Menampilkan Berkas Unit

      Untuk menampilkan berkas unit yang telah dimuat systemd ke dalam sistemnya, Anda dapat menggunakan perintah cat (ini telah ditambahkan dalam systemd versi 209). Misalnya, untuk melihat berkas unit daemon penjadwalan atd, kita dapat mengetikkan:

      • systemctl cat atd.service

      Output

      [Unit] Description=ATD daemon [Service] Type=forking ExecStart=/usr/bin/atd [Install] WantedBy=multi-user.target

      Keluaran adalah berkas unit yang diketahui systemd sebagai proses yang sedang berjalan. Ini dapat menjadi hal penting jika Anda baru-baru ini telah memodifikasi berkas unit atau jika Anda mengesampingkan beberapa opsi tertentu dalam fragmen berkas unit (kita akan membahasnya nanti).

      Menampilkan Dependensi

      Untuk melihat pohon dependensi unit, Anda dapat menggunakan perintah list-dependencies:

      • systemctl list-dependencies sshd.service

      Perintah ini akan menampilkan pemetaan hierarki yang harus ditangani agar dapat memulai unit tersebut. Dependensi dalam konteks ini meliputi unit-unit yang diperlukan oleh atau yang diinginkan oleh unit di atasnya.

      Output

      sshd.service ├─system.slice └─basic.target ├─microcode.service ├─rhel-autorelabel-mark.service ├─rhel-autorelabel.service ├─rhel-configure.service ├─rhel-dmesg.service ├─rhel-loadmodules.service ├─paths.target ├─slices.target . . .

      Dependensi rekursif hanya ditampilkan untuk unit .target, yang menandakan keadaan sistem. Untuk menampilkan daftar semua dependensi secara rekursif, sertakan bendera --all.

      Untuk menampilkan dependensi terbalik (unit yang bergantung pada unit yang ditentukan), Anda dapat menambahkan bendera --reverse pada perintah. Bendera lain yang berguna adalah --before dan --after, yang dapat digunakan untuk menampilkan unit yang bergantung pada unit yang ditentukan yang masing-masing dimulai sebelum dan setelah unit itu sendiri.

      Memeriksa Properti Unit

      Untuk melihat properti tingkat rendah dari suatu unit, Anda dapat menggunakan perintah show. Perintah ini akan menampilkan daftar properti yang diatur untuk unit yang ditentukan menggunakan format key=value:

      • systemctl show sshd.service

      Output

      Id=sshd.service Names=sshd.service Requires=basic.target Wants=system.slice WantedBy=multi-user.target Conflicts=shutdown.target Before=shutdown.target multi-user.target After=syslog.target network.target auditd.service systemd-journald.socket basic.target system.slice Description=OpenSSH server daemon . . .

      Jika ingin menampilkan properti tunggal, Anda dapat memberikan bendera -p bersama nama properti. Misalnya, untuk melihat konflik yang dimiliki unit sshd.service, Anda dapat mengetikkan:

      • systemctl show sshd.service -p Conflicts

      Output

      Conflicts=shutdown.target

      Melakukan Masking dan Unmasking Unit

      Di bagian manajemen layanan, kita telah melihat cara menghentikan atau menonaktifkan layanan, tetapi systemd juga memiliki kemampuan untuk menandai suatu unit menjadi tidak dapat dimulai sama sekali, secara otomatis atau manual, dengan menautkannya ke /dev/null. Perintah ini disebut masking unit, dan dapat dilakukan dengan perintah mask:

      • sudo systemctl mask nginx.service

      Perintah ini akan mencegah layanan Nginx dimulai, secara otomatis atau manual, selama unit tersebut diberi mask.

      Jika Anda memeriksa list-unit-files, Anda akan melihat layanan kini tercantum sebagai diberi mask:

      • systemctl list-unit-files

      Output

      . . . kmod-static-nodes.service static ldconfig.service static mandb.service static messagebus.service static nginx.service masked quotaon.service static rc-local.service static rdisc.service disabled rescue.service static . . .

      Jika Anda berupaya memulai layanan, Anda akan melihat pesan seperti ini:

      • sudo systemctl start nginx.service

      Output

      Failed to start nginx.service: Unit nginx.service is masked.

      Untuk melakukan unmask di suatu unit, agar unit dapat digunakan lagi, gunakan perintah unmask:

      • sudo systemctl unmask nginx.service

      Ini akan mengembalikan unit ke keadaan sebelumnya, yang memungkinkannya dimulai atau diaktifkan.

      Mengedit Berkas Unit

      Walaupun format spesifik untuk berkas unit berada di luar lingkup tutorial ini, systemctl memberikan mekanisme bawaan untuk mengedit dan memodifikasi berkas unit jika Anda perlu membuat penyesuaian. Fungsionalitas ini ditambahkan dalam systemd versi 218.

      Perintah edit secara asali akan membuka cuplikan berkas unit untuk unit tersebut:

      • sudo systemctl edit nginx.service

      Ini akan berupa berkas kosong yang dapat digunakan untuk mengesampingkan atau menambahkan arahan ke definisi unit. Direktori akan dibuat dalam direktori /etc/systemd/system yang berisi nama unit dengan tambahan .d. Misalnya, untuk nginx.service, suatu direktori bernama nginx.service.d akan dibuat.

      Di dalam direktori ini, cuplikan akan dibuat dengan nama override.conf. Bila unit dimuat, systemd dalam memori akan menggabungkan cuplikan yang dikesampingkan dengan berkas unit penuh. Arahan cuplikan akan menjadi prioritas daripada yang ada dalam berkas unit asli.

      Jika Anda ingin mengedit berkas unit penuh alih-alih membuat cuplikan, Anda dapat memberikan bendera --full:

      • sudo systemctl edit --full nginx.service

      Perintah ini akan memuat berkas unit saat ini ke dalam editor, yang dapat dimodifikasi. Ketika keluar dari editor, berkas yang diubah ditulis ke /etc/systemd/system, yang akan menjad prioritas dari definisi unit sistem (biasanya ditemukan di /lib/systemd/system).

      Untuk menghapus tambahan yang telah Anda buat, hapus direktori konfigurasi .d unit atau berkas layanan yang dimodifikasi dari /etc/systemd/system. Misalnya, untuk menghapus cuplikan, kita dapat mengetikkan:

      • sudo rm -r /etc/systemd/system/nginx.service.d

      Untuk menghapus berkas unit yang dimodifikasi sepenuhnya, kita ketikkan:

      • sudo rm /etc/systemd/system/nginx.service

      Setelah menghapus berkas atau direktori, Anda harus memuat ulang proses systemd agar tidak lagi berupaya merujuk berkas-berkas ini dan kembali menggunakan salinan sistem. Anda dapat melakukannya dengan mengetikkan:

      • sudo systemctl daemon-reload

      Menyesuaikan Keadaan Sistem (Runlevel) dengan Target

      Target adalah berkas unit khusus yang menggambarkan keadaan sistem atau titik sinkronisasi. Seperti unit lainnya, berkas yang mendefinisikan target dapat diidentifikasi melalui akhirannya, yang dalam hal ini adalah .target. Target tidak mencocokkan dirinya sendiri, melainkan digunakan untuk mengelompokkan unit lain menjadi satu.

      Perintah ini dapat digunakan untuk membawa sistem ke keadaan tertentu, seperti sistem init lainnya yang menggunakan runlevel. Semua itu digunakan sebagai referensi ketika fungsi tertentu tersedia, yang memungkinkan Anda menentukan keadaan yang diinginkan sebagai ganti unit individual yang diperlukan untuk menghasilkan keadaan itu.

      Misalnya, ada swap.target yang digunakan untuk menunjukkan bahwa swap siap digunakan. Unit yang menjadi bagian dari proses ini dapat menyinkronkan dengan target ini dengan menunjukkannya dalam konfigurasi bahwa unit tersebut WantedBy= atau RequiredBy= oleh swap.target. Unit yang mengharuskan swap tersedia dapat menentukan syarat ini menggunakan spesifikasi Wants=, Requires=, dan After= untuk menandakan sifat hubungannya.

      Mendapatkan dan Mengatur Target Asali

      Proses systemd memiliki target asali yang digunakannya saat melakukan boot sistem. Memenuhi kaskade dependensi dari target tunggal itu akan membawa sistem ke keadaan yang diinginkan. Untuk menemukan target asali bagi sistem Anda, ketikkan:

      Output

      multi-user.target

      Jika ingin menetapkan target asali yang berbeda, Anda dapat menggunakan set-default. Misalnya, jika Anda telah menginstal desktop grafis dan ingin agar sistem melakukan boot ke desktop grafis secara asali, Anda dapat mengubah target asalinya:

      • sudo systemctl set-default graphical.target

      Menampilkan Daftar Target yang Tersedia

      Anda bisa mendapatkan daftar target yang tersedia di sistem dengan mengetikkan:

      • systemctl list-unit-files --type=target

      Tidak seperti runlevel, beberapa target dapat aktif sekaligus. Target aktif menandakan bahwa systemd berupaya memulai semua unit yang terikat ke target dan tidak mencoba untuk memutusnya lagi. Untuk melihat semua target aktif, ketikkan:

      • systemctl list-units --type=target

      Mengisolasi Target

      Bisa saja memulai semua unit yang telah dikaitkan dengan target dan menghentikan semua unit yang bukan bagian dari pohon dependensi. Perintah yang kita perlukan untuk melakukannya disebut isolate. Ini mirip dengan mengubah runlevel di sistem init lainnya.

      Misalnya, jika Anda beroperasi di lingkungan grafis dengan graphical.target aktif, Anda dapat mematikan sistem grafis dan memasukkan sistem ke bentuk baris perintah multipengguna dengan mengisolasi multi-user.target. Karena graphical.target bergantung pada multi-user.target, tetapi tidak ada cara lainnya lagi, semua unit grafis akan dihentikan.

      Anda mungkin perlu melihat dependensi target yang diisolasi sebelum melakukan prosedur ini untuk memastikan bahwa Anda tidak menghentikan layanan penting:

      • systemctl list-dependencies multi-user.target

      Bila Anda puas dengan unit yang akan dibiarkan tetap aktif, Anda dapat mengisolasi target dengan mengetikkan:

      • sudo systemctl isolate multi-user.target

      Menggunakan Pintasan untuk Kejadian Penting

      Ada beberapa target yang didefinisikan untuk kejadian penting seperti mematikan daya atau melakukan boot ulang. Namun, systemctl juga memiliki beberapa pintasan yang memberikan beberapa fungsi tambahan.

      Misalnya, untuk menempatkan sistem ke dalam mode pertolongan (pengguna tunggal), Anda dapat menggunakan perintah rescue sebagai ganti isolate rescue.target:

      Perintah ini akan memberikan fungsi tambahan yang memperingatkan semua pengguna yang log masuk tentang kejadian tersebut.

      Untuk menghentikan sistem, Anda dapat menggunakan perintah halt:

      Untuk mulai mematikan daya sepenuhnya, Anda dapat menggunakan perintah poweroff:

      Menyalakan ulang dapat dimulai dengan perintah reboot:

      Ini semua akan memperingatkan para pengguna yang log masuk mengenai kejadian tersebut, satu-satunya hal yang tidak akan dilakukan oleh menjalankan atau mengisolasi target. Harap diperhatikan bahwa kebanyakan mesin akan menautkan perintah yang lebih pendek dan lebih konvensional untuk operasi ini agar berfungsi secara benar dengan systemd.

      Misalnya, untuk melakukan boot ulang sistem, Anda biasanya dapat mengetikkan:

      Kesimpulan

      Saat ini, Anda sudah memahami beberapa kemampuan dasar dari perintah systemctl yang memungkinkan Anda berinteraksi dengan dan mengendalikan instans systemd. Utilitas systemctl adalah titik utama interaksi Anda untuk manajemen layanan dan keadaan sistem.

      Walaupun systemctl terutama beroperasi dengan proses inti systemd, ada beberapa komponen lain di ekosistem systemd yang dikendalikan oleh utilitas lain. Kemampuan lainnya, seperti manajemen log dan sesi pengguna yang ditangani oleh daemon terpisah dan utilitas manajemen (masing-masing yaitu journald/journalctl dan logind/loginctl). Menyisihkan waktu untuk memahami berbagai alat dan daemon lain akan membuat manajemen menjadi tugas yang lebih mudah.



      Source link

      CSS Grid Layout: The Fr Unit


      While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or
      edited it to ensure you have an error-free learning experience. It’s on our list, and we’re working on it!
      You can help us out by using the “report an issue” button at the bottom of the tutorial.

      Introduction

      With CSS Grid Layout, we get a new flexible unit: the Fr unit. Fr is a fractional unit and 1fr is for 1 part of the available space. The following are a few examples of the fr unit at work. The grid items in these examples are placed onto the grid with grid areas.

      .container {
        display: grid;
      
        grid-template-columns: 1fr 1fr 1fr 1fr;
        grid-template-rows: 100px 200px 100px;
      
        grid-template-areas:
              "head head2 . side"
              "main main2 . side"
              "footer footer footer footer";
      }
      

      The 4 columns each take up the same amount of space.

      Head

      Head 2

      Main

      Main 2

      Side

      Footer

      Examples using fr

      Here’s the same example from above with different fr values. Notice the change in the layout:

      .container {
        /* ... */
      
        grid-template-columns: 1fr 1fr 40px 20%;
        grid-template-rows: 100px 200px 100px;
      
        /* ... */
      }
      

      Head

      Head 2

      Main

      Main 2

      Side

      Footer


      In the following last example, the sidebar item covers 2fr, so it’ll be the same width as the items that span the 1st and 2nd columns:

      .container {
        /* ... */
      
        grid-template-columns: 1fr 1fr 40px 2fr;
        grid-template-rows: 100px 200px 100px;
      
        /* ... */
      }
      

      Head

      Head 2

      Main

      Main 2

      Side

      Footer

      Mixed Units

      As you saw in the previous examples, you can mix fr values with fixed and percentage values. The fr values will be divided between the space that’s left after what’s taken by the other values.

      For example, if you have a grid with 4 columns as in the following snippet, the 1st column will be 300px, the second 80px (10% of 800px), the 3rd and 4th columns will be 210px (each occupying half of the remaining space):

      main {
        width: 800px;
        display: grid;
        grid-template-columns: 300px 10% 1fr 1fr;
        /* 300px 80px 210px 210px */
      
        grid-template-rows: auto;
      }
      



      Source link