Sebagai administrator sistem, shell adalah bagian dari operasi sehari-hari. Kerang sering memberikan lebih banyak pilihan dan fleksibilitas daripada antarmuka pengguna grafis (GUI). Tugas berulang harian dapat dengan mudah diotomatisasi oleh skrip, atau tugas dapat dijadwalkan untuk dijalankan pada waktu tertentu di siang hari. Shell menyediakan cara yang nyaman untuk berinteraksi dengan sistem dan memungkinkan Anda melakukan lebih banyak dalam waktu yang lebih singkat. Ada banyak shell yang berbeda, termasuk Bash, zsh, tcsh, dan PowerShell.
Dalam posting blog dua bagian ini, saya membagikan beberapa kalimat Bash yang saya gunakan untuk mempercepat pekerjaan saya dan memberikan lebih banyak waktu untuk minum kopi. Dalam posting awal ini, saya akan membahas sejarah, argumen terakhir, bekerja dengan file dan direktori, membaca konten file, dan fungsi Bash. Di bagian kedua, saya akan memeriksa variabel shell, perintah find, deskriptor file, dan menjalankan operasi dari jarak jauh.
Gunakan perintah riwayat
history
perintah adalah salah satu yang berguna. History
memungkinkan saya untuk melihat perintah apa yang saya jalankan pada sistem atau argumen tertentu yang diteruskan ke perintah itu. Saya menggunakan history
untuk menjalankan kembali perintah tanpa harus mengingat apapun.
Catatan perintah terbaru disimpan secara default di ~/.bash_history.
Lokasi ini dapat diubah dengan memodifikasi variabel shell HISTFILE. Ada variabel lain, seperti HISTSIZE (baris untuk disimpan dalam memori untuk sesi saat ini) dan HISTFILESIZE (berapa banyak baris untuk disimpan dalam file riwayat). Jika Anda ingin tahu lebih banyak tentang history
, lihat man bash
.
Katakanlah saya menjalankan perintah berikut:
$> sudo systemctl status sshd
Bash memberi tahu saya bahwa layanan sshd tidak berjalan, jadi hal berikutnya yang ingin saya lakukan adalah memulai layanan. Saya telah memeriksa statusnya dengan perintah saya sebelumnya. Perintah itu disimpan di history
, jadi saya bisa referensi itu. Saya cukup menjalankan:
$> !!:s/status/start/
sudo systemctl start sshd
Ekspresi di atas memiliki konten berikut:
- !! - ulangi perintah terakhir dari sejarah
- :s/status/start/ - pengganti status dengan mulai
Hasilnya adalah layanan sshd dimulai.
Selanjutnya, saya meningkatkan nilai HISTSIZE default dari 500 menjadi 5000 dengan menggunakan perintah berikut:
$> echo “HISTSIZE=5000” >> ~/.bashrc && source ~/.bashrc
Bagaimana jika saya ingin menampilkan tiga perintah terakhir dalam riwayat saya? Saya memasukkan:
$> history 3
1002 ls
1003 tail audit.log
1004 history 3
Saya menjalankan tail
di audit.log
dengan mengacu pada nomor baris sejarah. Dalam hal ini, saya menggunakan baris 1003:
$> !1003
tail audit.log
..
..
Bayangkan Anda telah menyalin sesuatu dari terminal lain atau browser Anda dan Anda secara tidak sengaja menempelkan salinan tersebut (yang Anda miliki di buffer salinan) ke terminal. Baris-baris itu akan disimpan dalam riwayat, yang di sini adalah sesuatu yang tidak Anda inginkan. Jadi di situlah unset HISTFILE &&exit berguna
$> unset HISTFILE && exit
atau
$> kill -9 $$
Referensikan argumen terakhir dari perintah sebelumnya
Ketika saya ingin membuat daftar isi direktori untuk direktori yang berbeda, saya mungkin sering berpindah antar direktori. Ada trik bagus yang dapat Anda gunakan untuk merujuk ke argumen terakhir dari perintah sebelumnya. Misalnya:
$> pwd
/home/username/
$> ls some/very/long/path/to/some/directory
foo-file bar-file baz-file
Pada contoh di atas, /some/very/long/path/to/some/directory
adalah argumen terakhir dari perintah sebelumnya.
Jika saya ingin cd
(ubah direktori) ke lokasi itu, saya memasukkan sesuatu seperti ini:
$> cd $_
$> pwd
/home/username/some/very/long/path/to/some/directory
Sekarang cukup gunakan karakter tanda hubung untuk kembali ke tempat saya sebelumnya:
$> cd -
$> pwd
/home/username/
Mengerjakan file dan direktori
Bayangkan saya ingin membuat struktur direktori dan memindahkan banyak file yang memiliki ekstensi berbeda ke direktori ini.
Pertama, saya membuat direktori sekaligus:
$> mkdir -v dir_{rpm,txt,zip,pdf}
mkdir: created directory 'dir_rpm'
mkdir: created directory 'dir_txt'
mkdir: created directory 'dir_zip'
mkdir: created directory 'dir_pdf'
Selanjutnya, saya memindahkan file berdasarkan ekstensi file ke setiap direktori:
$> mv -- *.rpm dir_rpm/
$> mv -- *.pdf dir_pdf/
$> mv -- *.txt dir_txt/
$> mv -- *.zip dir_txt/
Karakter tanda hubung ganda --
berarti Akhir Pilihan. Bendera ini mencegah file yang dimulai dengan tanda hubung diperlakukan sebagai argumen.
Selanjutnya saya ingin mengganti/memindahkan semua file *.txt ke file *.log, jadi saya masukkan:
$> for f in ./*.txt; do mv -v ”$file” ”${file%.*}.log”; done
renamed './file10.txt' -> './file10.log'
renamed './file1.txt' -> './file1.log'
renamed './file2.txt' -> './file2.log'
renamed './file3.txt' -> './file3.log'
renamed './file4.txt' -> './file4.log'
Alih-alih menggunakan for
loop di atas, saya dapat menginstal prename
perintah dan capai tujuan di atas seperti ini:
$> prename -v 's/.txt/.log/' *.txt
file10.txt -> file10.log
file1.txt -> file1.log
file2.txt -> file2.log
file3.txt -> file3.log
file4.txt -> file4.log
Seringkali, ketika memodifikasi file konfigurasi, saya membuat salinan cadangan dari yang asli dengan menggunakan perintah salin dasar. Misalnya:
$> cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0.back
Seperti yang Anda lihat, mengulangi seluruh jalur dan menambahkan .back ke file tidak begitu efisien dan mungkin rawan kesalahan. Ada cara yang lebih pendek dan lebih rapi untuk melakukan ini. Ini dia:
$> cp /etc/sysconfig/network-scripts/ifcfg-eth0{,.back}
Anda dapat melakukan pemeriksaan yang berbeda pada file atau variabel. Jalankan help test
untuk informasi lebih lanjut.
Gunakan perintah berikut untuk mengetahui apakah suatu file adalah tautan simbolis:
$> [[ -L /path/to/file ]] && echo “File is a symlink”
Inilah masalah yang saya temui baru-baru ini. Saya ingin gunzip/untar banyak file sekaligus. Tanpa pikir panjang, saya mengetik:
$> tar zxvf *.gz
Hasilnya adalah:
tar: openvpn.tar.gz: Not found in archive
tar: Exiting with failure status due to previous errors
File tarnya adalah:
iptables.tar.gz
openvpn.tar.gz
…..
Mengapa tidak berhasil, dan mengapa ls -l *.gz
bekerja sebagai gantinya? Di bawah tenda, terlihat seperti ini:
$> tar zxvf *.gz
Ditransformasikan sebagai berikut:
$> tar zxvf iptables.tar.gz openvpn.tar.gz
tar: openvpn.tar.gz: Not found in archive
tar: Exiting with failure status due to previous errors
tar
perintah diharapkan untuk menemukan openvpn.tar.gz dalam iptables.tar.gz. Saya memecahkan ini dengan sederhana for
lingkaran:
$> for f in ./*.gz; do tar zxvf "$f"; done
iptables.log
openvpn.log
Saya bahkan dapat membuat kata sandi acak dengan menggunakan Bash! Ini contohnya:
$> alphanum=( {a..z} {A..Z} {0..9} ); for((i=0;i<=${#alphanum[@]};i++)); do printf '%s' "${alphanum[@]:$((RANDOM%255)):1}"; done; echo
Berikut adalah contoh yang menggunakan OpenSSL:
$> openssl rand -base64 12
JdDcLJEAkbcZfDYQ
Membaca file baris demi baris
Asumsikan saya memiliki file dengan banyak alamat IP dan ingin beroperasi pada alamat IP tersebut. Misalnya, saya ingin menjalankan dig
untuk mengambil informasi reverse-DNS untuk alamat IP yang tercantum dalam file. Saya juga ingin melewati alamat IP yang dimulai dengan komentar (# atau hashtag).
Saya akan menggunakan fileA sebagai contoh. Isinya adalah:
10.10.12.13 some ip in dc1
10.10.12.14 another ip in dc2
#10.10.12.15 not used IP
10.10.12.16 another IP
Saya dapat menyalin dan menempelkan setiap alamat IP, lalu menjalankan dig
secara manual:
$> dig +short -x 10.10.12.13
Atau saya bisa melakukan ini:
$> while read -r ip _; do [[ $ip == \#* ]] && continue; dig +short -x "$ip"; done < ipfile
Bagaimana jika saya ingin menukar kolom di fileA? Misalnya, saya ingin meletakkan alamat IP di kolom paling kanan sehingga fileA terlihat seperti ini:
some ip in dc1 10.10.12.13
another ip in dc2 10.10.12.14
not used IP #10.10.12.15
another IP 10.10.12.16
Saya menjalankan:
$> while read -r ip rest; do printf '%s %s\n' "$rest" "$ip"; done < fileA
Gunakan fungsi Bash
Fungsi di Bash berbeda dengan yang ditulis dengan Python, C, awk, atau bahasa lainnya. Di Bash, fungsi sederhana yang menerima satu argumen dan mencetak "Hello world" akan terlihat seperti ini:
func() { local arg=”$1”; echo “$arg” ; }
Saya dapat memanggil fungsi seperti ini:
$> func foo
Terkadang suatu fungsi memanggil dirinya sendiri secara rekursif untuk melakukan tugas tertentu. Misalnya:
func() { local arg="$@"; echo "$arg"; f "$arg"; }; f foo bar
Rekursi ini akan berjalan selamanya dan menggunakan banyak sumber daya. Di Bash, Anda dapat menggunakan FUNCNEST untuk membatasi rekursi. Dalam contoh berikut, saya menetapkan FUNCNEST=5 untuk membatasi rekursi menjadi lima.
func() { local arg="$@"; echo "$arg"; FUNCNEST=5; f "$arg"; }; f foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
bash: f: maximum function nesting level exceeded (5)
Gunakan fungsi untuk mengambil file terbaru atau terlama
Berikut adalah contoh fungsi untuk menampilkan file terbaru di direktori tertentu:
latest_file()
{
local f latest
for f in "${1:-.}"/*
do
[[ $f -nt $latest ]] && latest="$f"
done
printf '%s\n' "$latest"
}
Fungsi ini menampilkan file tertua di direktori tertentu:
oldest_file()
{
local f oldest
for file in "${1:-.}"/*
do
[[ -z $oldest || $f -ot $oldest ]] && oldest="$f"
done
printf '%s\n' "$oldest"
}
Ini hanyalah beberapa contoh cara menggunakan fungsi di Bash tanpa menjalankan perintah eksternal lainnya.
Saya terkadang mendapati diri saya mengetik perintah berulang-ulang dengan banyak parameter. Salah satu perintah yang sering saya gunakan adalah kubectl
(CLI Kubernetes). Saya lelah menjalankan perintah yang panjang ini! Berikut perintah aslinya:
$> kubectl -n my_namespace get pods
atau
$> kubectl -n my_namespace get rc,services
Sintaks ini mengharuskan saya untuk secara manual memasukkan -n my_namespace
setiap kali saya menjalankan perintah. Ada cara yang lebih mudah untuk melakukannya menggunakan fungsi:
$> kubectl () { command kubectl -n my_namespace ”$@” ; }
Sekarang saya bisa menjalankan kubectl
tanpa harus mengetik -n namespace
setiap kali:
$> kubectl get pods
Saya dapat menerapkan teknik yang sama untuk perintah lain.
Menutup
Ini hanya beberapa trik luar biasa yang ada untuk Bash. Di bagian kedua, saya akan menunjukkan beberapa contoh lagi, termasuk penggunaan find dan eksekusi jarak jauh. Saya mendorong Anda untuk mempraktikkan trik ini untuk membuat tugas administrasi baris perintah Anda lebih mudah dan lebih akurat.
[ Kursus online gratis:Tinjauan teknis Red Hat Enterprise Linux. ]