Untuk mengoptimalkan asyncio dengan multithreading, ada beberapa langkah yang dapat Anda ikuti:

  1. Identifikasi tugas I/O-bound: Tentukan tugas mana dalam aplikasi Anda yang merupakan operasi I/O-bound, seperti permintaan jaringan, operasi basis data, atau operasi file. Ini adalah tugas-tugas yang umumnya dapat mengambil waktu yang lama karena menunggu respons dari I/O.

  2. Gunakan fungsi I/O-bound dalam executor: Buat fungsi I/O-bound Anda agar dapat dijalankan dalam executor (pools of threads atau ProcessPoolExecutor). Anda dapat menggunakan loop.run_in_executor() untuk mengirimkan fungsi I/O-bound ke dalam executor.

  3. Tentukan ukuran thread pool: Saat membuat executor, tetapkan ukuran pool thread yang sesuai dengan jumlah yang optimal untuk lingkungan Anda. Ini dapat dilakukan dengan mengatur parameter max_workers pada ThreadPoolExecutor atau ProcessPoolExecutor.

  4. Gunakan asyncio.gather(): Gunakan asyncio.gather() untuk menjalankan coroutines secara paralel. Anda dapat mengelompokkan coroutines yang menggunakan loop.run_in_executor() ke dalam asyncio.gather() untuk menjalankan tugas I/O-bound secara bersamaan.

  5. Gunakan asyncio.Event() untuk sinkronisasi: Jika Anda perlu melakukan sinkronisasi antara coroutines yang menggunakan thread pool, Anda dapat menggunakan asyncio.Event(). Dengan asyncio.Event(), Anda dapat menunggu hingga semua coroutines selesai sebelum melanjutkan eksekusi.

  6. Perhatikan GIL: Jika tugas Anda juga termasuk tugas CPU-bound yang membutuhkan paralelisme, ingat bahwa CPython menggunakan Global Interpreter Lock (GIL) yang membatasi eksekusi konkuren dari kode Python pada tingkat thread. Dalam hal ini, mempertimbangkan menggunakan multiprocessing daripada multithreading mungkin lebih efektif.

  7. Uji dan perbaiki: Lakukan pengujian kinerja dan monitor aplikasi Anda untuk melihat apakah ada peningkatan dalam penggunaan sumber daya dan waktu eksekusi. Jika perlu, lakukan penyesuaian ukuran thread pool atau metode lainnya untuk meningkatkan kinerja.

  8. Penting untuk dicatat bahwa efektivitas optimasi asyncio dengan multithreading akan bervariasi tergantung pada sifat tugas Anda, lingkungan aplikasi, dan spesifikasi sistem yang Anda gunakan. Jadi, penting untuk menguji dan memonitor performa aplikasi Anda untuk mendapatkan pemahaman yang lebih baik tentang cara terbaik untuk mengoptimalkan asyncio dengan multithreading dalam konteks aplikasi Anda.

Anda dapat menggunakan teknik yang disebut thread pooling. Thread pooling memungkinkan Anda memanfaatkan beberapa thread untuk memproses operasi I/O-bound secara bersamaan, meningkatkan throughput secara keseluruhan dari aplikasi asyncio Anda. Berikut adalah contoh cara Anda dapat mengoptimalkan asyncio dengan multithreading menggunakan thread pool:

import asyncio
import concurrent.futures

# Fungsi untuk melakukan operasi I/O-bound / blocking function
def perform_io_operation():
    # Lakukan operasi I/O-bound
    print("operasi")

# Coroutine yang menggunakan fungsi I/O-bound
async def my_coroutine():
    loop = asyncio.get_event_loop()

    # Submit fungsi I/O-bound ke dalam thread pool
    with concurrent.futures.ThreadPoolExecutor() as executor:
        result = await loop.run_in_executor(executor, perform_io_operation)

    # Proses hasil
    print("hasil")

# Jalankan event loop
async def main():
    # Buat instance dari coroutine
    coro = my_coroutine()

    # Jalankan coroutine
    await asyncio.gather(coro)

# Mulai event loop
asyncio.run(main())

Dalam contoh ini, perform_io_operation mewakili operasi I/O-bound yang ingin Anda jalankan secara asinkron. Coroutine my_coroutine menggunakan loop.run_in_executor() untuk mengirimkan fungsi I/O-bound ke dalam thread pool untuk dieksekusi. Dengan menggunakan ThreadPoolExecutor, Anda dapat memproses beberapa operasi I/O-bound secara bersamaan.

Untuk mengoptimalkan kinerja, Anda dapat menyesuaikan ukuran thread pool dengan menentukan parameter max_workers saat membuat ThreadPoolExecutor. Misalnya, Anda dapat mengatur max_workers menjadi jumlah inti CPU untuk efektivitas penggunaan sumber daya yang tersedia.

Dengan menggunakan thread pool, Anda memungkinkan asyncio untuk menangani operasi I/O-bound dengan menggunakan beberapa thread, sementara event loop dapat melanjutkan eksekusi tugas lainnya. Pendekatan ini dapat secara signifikan meningkatkan kinerja dan responsivitas aplikasi asyncio Anda.

Perlu diingat bahwa thread pooling paling efektif untuk operasi I/O-bound di mana thread menghabiskan sebagian besar waktunya menunggu I/O selesai. Jika Anda memiliki operasi CPU-bound yang membutuhkan paralelisme, multiprocessing atau teknik lainnya mungkin lebih cocok.

Selalu pastikan untuk menangani dengan baik sumber daya bersama atau masalah sinkronisasi ketika menggunakan thread pooling dengan asyncio untuk memastikan keamanan thread dan mencegah kondisi perlombaan (race conditions).

Dengan mengoptimalkan asyncio dengan multithreading melalui thread pooling, Anda dapat mencapai penggunaan sumber daya sistem yang lebih baik dan meningkatkan kinerja operasi I/O asinkron Anda.

Rockchip-RK3588M

Rockchip RK3588M adalah varian otomotif dari Rockchip RK3588, sebuah SoC Cortex-A76/A55 octa-core yang mendukung setidaknya 6 tampilan Full HD dan 16 input kamera, serta dapat menjalankan secara simultan dashboard mobil, hiburan di dalam kendaraan, cermin belakang digital, monitor sandaran kepala, sistem ADAS, dan lain-lain.

Frekuensi inti Cortex-A76 dibatasi hingga 2.1 GHz, dan inti Cortex-A55 hingga 1.7 GHz, berbeda dengan RK3588 yang memiliki frekuensi 2.4 dan 1.8 GHz, mungkin untuk beroperasi dalam rentang suhu yang lebih luas yang dibutuhkan oleh pasar otomotif. Saat ini saya belum menemukan lembar data RK3588M, namun kita dapat menemukan lebih banyak detail melalui papan utama otomotif Firefly AIO-3588MQ yang dibangun di sekitar prosesor RK3588M.

Rockchip RK3588M adalah SBC otomotif (Single Board Computer).

Rockchip-RK3588M

Firefly AIO-3588MQ specifications:

SoC – Rockchip RK3588M octa-core processor with
    CPU 4x Cortex-A76 cores @ up to 2.1 GHz, 4x Cortex-A55 cores @ up to 1.7 GHz
    Arm Mali-G610 MP4 GPU with OpenGL ES 3.2, OpenCL 2.2, Vulkan 1.1 support
    6 TOPS AI accelerator
    Video decoding:
        8Kp60 H.265/VP9/AVS2
         8Kp30 H.264 AVC/MVC
         4Kp60 AV1
        1080p60 MPEG-2/-1/VC-1/VP8
    Video encoding – 8Kp30 H.265 / H.264
    Up to 32-channel 1080p30 decoding and 16-channel 1080p30 encoding can be achieved.
System Memory – 4GB, 8GB, or 16GB (Up to 32GB optional) 64-bit LPDDR4/LPDDR4x/LPDDR5
Storage – M.2 SATA3.0 SSD (2242), microSD card slot
Video Output
    HDMI 2.1 up to 8Kp60 or 4Kp120
    DisplayPort 1.4 up to 8Kp30fps (via USB-C)
    VGA up to 1080p60
    eDP1.3 connector up to 4Kp60Hz
    2x MIPI DSI display interfaces up to 4Kp60
    Up to 6 independent displays
Video Input
    Dual 16M ISP on RK3588M
    HDMI input up to 4Kp60 with support for HDCP 2.3
    30-pin MIPI-CSI(0) connector configurable as 1x 4-lane or 2x 2-lane
    Board-to-board connector with 4-lane MIPI_CSI(1) or 2x 2-lane MIPI-CSI(1) + 2x MIPI_D/C (4-lane DPHY v2.0 or 3-lane CPHY V1.1)
Audio
    3.5mm audio jack
    Digital audio output via HDMI 2.1 and DP 1.4 ports
    Line-in via header
    Microphone input
Networking
    2x Gigabit Ethernet RJ45 ports
    2.4GHz/5GHz dual-band WiFi 6 (802.11a/b/g/n/ac/ax), Bluetooth 5.0
    Optional 4G LTE/5G cellular
USB – 4x USB 3.1 Gen1, 1x USB Type-C (OTG/DP1.4) port, and 3x USB 2.0 (via pin header)
Serial – 2x RS232, RS485, CAN Bus
Expansion
    4-lane PCIe 3.0 slot
    mPCIe and M.2 sockets for wireless modules
    20-pin 2mm-pitch header with GPIO, ADC, SPI, I2C, LED, REV, PWR, RST
Power Supply – 12V DC / 2A recommended via 5.5/2.1mm DC jack or 4-pin header
Power Consumption
    Idle – About 0.72W (12V/60mA)
    Typical – About 2.4W(12V/200mA)
    Max – About 14.4W(12V/1200mA)
Dimensions – 146 x 102 x 37.5mm
Weight – Around 200 grams
Temperature Range – Operating: -40°C to 85°C in product page but -20°C to 60°C in the board’s datasheet
Humidity – 10%~80 % (storage)

Rockchip-RK3588M

Perusahaan ini menyediakan dukungan untuk Android 12.0, Ubuntu Desktop dan Server, Debian 11, dan buildroot RTLinux untuk papan // sistem-on-module. Firefly juga menyebutkan dukungan Kernel-based Virtual Machine (KVM) dan Docker container, karena akan diperlukan untuk mendukung bagian-bagian perangkat lunak yang kritis (misalnya, dashboard) dan non-kritis (misalnya, infotainment) dengan sistem operasi terisolasi yang mungkin berbeda. Dokumentasi teknis dapat ditemukan di Wiki (https://wiki.t-firefly.com/en/iCore-3588MQ/started.html) untuk memulai dengan Android, Linux, dan RTLinux.

Pertama kali saya mengetahui tentang RK3588M adalah dalam sebuah demo pada bulan Februari lalu di RKDC (Rockchip Developer Conference), yang menunjukkan sistem yang mengoperasikan empat tampilan independen dan dua gamepad.

“Cython adalah modul dan bahasa yang digunakan oleh para pengembang Python untuk mempercepat kode mereka”c

Bagaimana Cython bekerja? Apa itu Cython? Haruskah Anda menulis semua kode Python Anda dengan Cython? Seberapa cepat Cython membuat kode Anda? Dan apakah selalu berhasil?

Dalam tutorial ini, kami akan memperkenalkan Anda pada Cython dan menjelaskan mengapa Anda harus menggunakannya saat menulis kode Python. Kami juga akan membahas pipa kompilasi Cython dan skenario penggunaan umum serta membimbing Anda dalam instalasi dan pengaturan.

Kami akan membahas hal berikut dengan contoh nyata:

  • Apa itu Cython?
  • Apa yang ditawarkan oleh Cython?
  • Pipa kompilasi Cython
  • Kapan menggunakan Cython
  • Perbandingan performa antara Python dan Cython

Tujuan panduan ini adalah membantu Anda memahami Cython dengan lebih baik dan bagaimana ia mempercepat Python menggunakan program pencarian bilangan prima sederhana.

Apa itu Cython?

Cython dapat dianggap sebagai modul dan bahasa pemrograman yang (secara berurutan) memperluas Python dengan mengaktifkan penggunaan tipe data statis yang diambil dari C/C++. Pada dasarnya, semua kode Python valid dalam Cython, tetapi tidak sebaliknya.

Ingatlah, Anda dapat mengonversi Python menjadi Cython dan sebaliknya. Jika ini sulit dipahami, pikirkan hubungan antara C dan C++ atau JavaScript dan TypeScript. Anda dapat langsung menyalin kode Python yang ada ke file Cython dan kemudian mengompilasinya untuk meningkatkan performa.

Apa yang ditawarkan oleh Cython?

Dalam pengetahuan umum, Python lebih efisien daripada C karena Python adalah bahasa tingkat tinggi. Meskipun demikian, ada kekurangan dalam menggunakan Python dibandingkan dengan C/C++.

Python efisien tetapi lambat. C, di sisi lain, kurang efisien tetapi lebih cepat daripada Python. Oleh karena itu, Cython bertujuan untuk memberikan semua keuntungan C ke Python sambil mempertahankan efisiensi yang diharapkan oleh pengembang Python.

Untuk memahaminya lebih lanjut, Anda perlu memahami terlebih dahulu bagaimana kode Python dieksekusi. Dalam proses eksekusi (yaitu, di interpreter), kode sumber Python melalui kompilator, yang bertindak sebagai penerjemah untuk mengonversi kode sumber menjadi bytecode yang independen dari platform.

Setelah itu, mesin virtual Python mengeksekusi bytecode baris per baris. Karena ini terjadi secara langsung selama waktu eksekusi, eksekusi baris per baris membuat proses tersebut lambat dibandingkan dengan bahasa yang dikompilasi.

gambar cython 1

Jika Anda membandingkannya dengan diagram blok bahasa yang dikompilasi, kode sumber diubah menjadi kode mesin yang dapat langsung dijalankan pada arsitektur. Ini sangat cepat dibandingkan dengan proses oleh interpreter.

Kekurangan dari pendekatan ini adalah bahwa kode mesin bergantung pada platform, yang berarti Anda tidak dapat menjalankan kode yang sama di platform yang berbeda.

Sekarang Anda dapat melihat apa yang kedua konsep tersebut tawarkan. C membawa tipe data statis ke Python dan Python membawa efisiensi ke C.

gambar cython 2

Pipeline kompilasi Cython

Seperti apa pipeline Cython? Kompilasi dalam Cython adalah proses dua langkah.

Pada langkah pertama, kode Cython Anda diubah menjadi kode C atau C++ yang dioptimalkan dan tidak tergantung pada platform. Dari sana, kode sumber C atau C++ diubah menjadi file objek bersama melalui compiler C atau C++. Namun, file objek bersama ini tergantung pada platform. Pada sistem operasi Linux atau Mac OS, file ini memiliki ekstensi *.so, sedangkan pada Windows memiliki ekstensi *.pyd.

gambar cython 3

Kapan Menggunakan Cython ?

Dalam situasi apa Anda mungkin perlu menggunakan Cython? Apakah itu bekerja di semua tempat setiap saat?

Nah, ya dan tidak. Menggunakan Cython di mana-mana tidak selalu menjamin peningkatan kecepatan. Namun, Anda dapat menggunakannya dalam fungsi yang melibatkan banyak operasi matematika dan iterasi loop. Hal ini karena mendefinisikan tipe sebelum menjalankan operasi membuatnya lebih mudah saat dilakukan eksekusi, terutama dalam loop di mana variabel dianalisis dan diulang beberapa kali.

Kasus penggunaan yang bagus lainnya adalah ketika Anda sudah memiliki perpustakaan C atau C++ yang membutuhkan antarmuka Python. Dalam hal ini, Anda dapat menggunakan Cython untuk membuat wrapper untuk perpustakaan tersebut.

Python vs. Cython: Membandingkan kinerja

Sekarang mari kita buat proyek contoh untuk melihat Cython dalam aksi.

Langkah pertama adalah membuka terminal, mengatur lingkungan yang aman untuk bekerja (opsional), dan menginstal Cython beserta dependensi yang diperlukan.

$ sudo apt install build-essential

Ini akan membuat kompiler gcc tersedia jika komputer Anda belum memiliki kompiler tersebut.

$ sudo apt install python3-venv

Ini menyediakan lingkungan aman bagi Anda untuk bekerja dengan aman. Langkah ini tidak diperlukan, tetapi selalu baik untuk membuat proyek Anda dalam lingkungan virtual terpisah agar dependensi tidak saling bertentangan.

$ sudo pip3 install cython

Ini menginstal Cython ke mesin Anda.

Setelah instalasi selesai, kita dapat mulai.

Dalam demonstrasi ini, kita akan menulis dua fungsi sederhana dalam satu file yang sama, yang disebut main.pyx, untuk mencari beberapa bilangan prima. Kita akan menulis satu dalam Python dasar dan satu lagi dalam Cython. Dari sana, kita akan menjalankan keduanya dan mengukur perbedaan waktu eksekusi.

Perhatikan bahwa semua file untuk demonstrasi ini akan berada dalam satu direktori. Juga, daripada menggunakan ekstensi .py dalam file ini, Anda akan menggunakan .pyx karena Anda sudah menginstal Cython di mesin atau lingkungan Anda.

# 1. The basic Python function

"""
Dalam fungsi ini, yang akan Anda harapkan sebagai nilai pengembalian adalah daftar dari beberapa angka pertama tergantung pada apa yang Anda masukkan sebagai parameter masukan. Daftar angka prima yang ditemukan akan kosong pada awalnya.
"""
def prime_finder_py ( amount ):
primes = []
found = 0
number = 2

while found < amount:
for x in primes:
    if number % x == 0:
    break
    else:
    primes.append ( number )

found += 1
number += 1

return primes

"""
Hal yang Anda periksa hanya pada baris 12 adalah apakah angka baru yang sedang Anda periksa dapat dibagi habis oleh angka prima. Angka yang ditambahkan ke dalam array hanya akan ada di sana jika tidak ada satu pun angka di bawahnya yang dapat membaginya.

Baris 19 memastikan bahwa perulangan berjalan dari satu angka ke angka berikutnya secara progresif, terlepas dari apakah itu ditambahkan ke dalam array angka prima.
"""

# 2. The Cython Function

"""
Pertama-tama, Anda harus mendefinisikan variabel-variabel ini karena Anda tidak ingin mendefinisikannya secara langsung saat sedang mencoba mengoptimalkan Python menggunakan sintaksis C.

Selain itu, dalam pemrograman C, Anda selalu harus mendefinisikan array Anda dengan ukuran tetap seperti yang saya lakukan pada baris 10.

Baris 13 adalah sebagai langkah pencegahan jika Anda memilih angka yang melebihi batas ini (yang dapat Anda ubah, by the way).
"""

def prime_finder_cy ( int amount ):
cdef int number, x, found
cdef prime[50000]
amount = min ( amount, 50000 )

found = 0
number = 2
while found < amount:
    for x in primes[ :found]:
    if number % x == 0:
        break
    else:
        primes[found] = number
        found += 1

    number += 1

return_list = [p for p in primes[ :found]]
return return_list


'''
Untuk loop for pada baris 19, Anda perlu menyesuaikannya sedikit karena Anda sebenarnya tidak ingin menjalankan seluruh nilai dari array tetap Anda bahkan ketika Anda tidak memiliki begitu banyak angka dalam array tersebut. Oleh karena itu, loop hanya perlu berjalan hingga indeks 'found'. Dengan cara itu, loop hanya akan berjalan hingga indeks terakhir dari 'found'.

Baris 28 memastikan bahwa Anda hanya memiliki elemen yang Anda butuhkan dan bukan seluruh panjang array.
'''

Seperti yang dapat Anda lihat, logika bagaimana kami menemukan angka prima sama persis. Anda tidak mengubah apa pun. Sebenarnya, Anda memiliki lebih banyak kode dalam sintaksis Cython.

Jika Anda melihat implementasi Cython, Anda akan melihat bahwa Anda memiliki array dengan ukuran tetap dengan slot kosong yang berlebihan. Anda memiliki definisi tipe dan beberapa kode tambahan. Anda mungkin berpikir ini akan menyebabkan kinerja yang lebih lambat karena fakta sederhana bahwa ada lebih banyak kode. Namun, Anda akan melihat bahwa kode Cython jauh lebih cepat daripada kode Python.

Buat file lain dalam direktori yang sama dan beri nama apa saja dengan ekstensi .py. Untuk contoh ini, saya memberi nama file saya setup.py.

Di dalam file setup.py, impor dari setuptools dan cythonize dari Cython.Build, seperti ini:

from setuptools import setup
from Cython.Build import cythonize

Yang perlu Anda lakukan di file ini adalah menambahkan potongan kode berikut:

from setuptools import setup
from Cython.Build import cythonize

setup ( ext_modules = cythonize ( ‘main.pyx’ ) )

Setelah itu, Anda tidak hanya menjalankannya di IDE Anda; Anda harus menjalankannya dari terminal. Buka direktori tersebut di terminal dan jalankan perintah berikut:

$ python setup.py build_ext --inplace

Perintah ini akan menghasilkan file main.c dan file .so jika Anda menggunakan Linux, atau file .pyd jika Anda menggunakan Windows.

Dari sini, Anda tidak lagi memerlukan file main.pyx. Anda hanya memerlukan file *.so dan file baru lainnya untuk menguji fungsi.

Anda dapat memberi nama file .py baru apa pun yang Anda inginkan; untuk tujuan contoh ini, kita akan namai test.py

Di file test.py, Anda perlu mengimpor main, yang merupakan file biner, dan time, yang akan Anda gunakan untuk membandingkan waktu eksekusi.

Jangan khawatir — Anda hampir selesai.

Setelah mengimpor main dan time, Anda dapat mulai memanggil fungsi dengan melihat impor main, seperti ini:

import main
import time

# example call
print( main.prime_finder_py(x) )
print( main.prime_finder_cy(x) )

'''
X dalam tanda kurung parameter adalah jumlah bilangan prima yang ingin ditampilkan oleh program.
'''

Sekarang saatnya untuk bagian yang menyenangkan.

Untuk menentukan waktu yang dibutuhkan oleh fungsi-fungsi, Anda perlu menambahkan variabel waktu dan menggunakan modul time yang telah Anda impor.

import main
import time

start_py = time.time() '''records time before function runs'''
print( main.prime_finder_py(x) )
end_py = time.time() '''records time after function has run'''

time_py = end_py – start_py

start_cy = time.time() '''records time before function runs'''
print( main.prime_finder_cy(x) )
end_cy = time.time() '''records time after function has run'''

time_cy = end_cy – start_cy

if time_cy < time_py:
print ( ‘ The Cython implementation is faster ’)
else:
print ( ‘The Python implementation is faster ’ )

Sebagian besar kode ini cukup sederhana. Pada dasarnya, jika Anda menjalankan file test.py ini di IDE Anda, bagian pertama akan mencatat waktu yang dibutuhkan oleh fungsi Python untuk berjalan. Bagian kedua melakukan hal yang sama untuk fungsi Cython. Pernyataan if membandingkan dua nilai waktu eksekusi yang dihitung dan mengevaluasi fungsi mana yang lebih cepat dari yang lain.

Perhatikan bahwa Anda harus menggunakan angka besar dalam parameter Anda, jika tidak Anda tidak akan melihat perbedaannya. Cobalah menggunakan 20.000 sebagai parameter dan lihat apa yang terjadi. Anda bahkan dapat mencoba menambahkan pernyataan cetak untuk melihat nilai yang tepat dari variabel waktu untuk setiap fungsi. Bersenang-senanglah dengan itu.

Bagaimanapun, ini hanya karena Cython telah menambahkan tipe statis. Anda tidak mengubah hal-hal kompleksitas algoritma atau menyimpan sesuatu secara tidak sengaja di cache. Pada dasarnya, Anda mengorbankan sebagian fleksibilitas Python untuk peningkatan besar dalam waktu eksekusi.

Kesimpulan

Sekarang setelah kita melalui latihan ini, apakah memperkenalkan Cython ke kode Python Anda membantu? Ya, tetapi tidak selalu.

Ketika operasi terikat pada CPU, artinya seluruh waktu runtime dihabiskan untuk memanipulasi beberapa nilai di dalam register CPU dan sedikit atau tidak ada pergerakan data yang diperlukan, Cython kemungkinan besar akan meningkatkan kinerja dengan memperkenalkan variabel yang diberi tipe statis dan pustaka objek bersama. Namun, ini tidak dapat membantu ketika operasi yang terikat pada IO (misalnya, membaca file besar dari disk) atau terikat pada jaringan (yaitu, mengunduh file dari server FTP) menjadi bottleneck.

Jadi, ketika memperkenalkan Cython ke kode Python Anda, Anda perlu melakukan profil pada kode Anda dan menentukan jenis bottleneck yang Anda miliki.

[METODE 1] Masuk dan Login ssh dengan menggunakan root akses

sudo su - 

Ubah /etc/profile dan tambahkan baris berikut ke bagian bawah file /etc/profile:

# command line audit logging
function log2syslog
{
   declare COMMAND
   COMMAND=$(fc -ln -0)
   logger -p local1.notice -t bash -i -- "${USER}:${COMMAND}"
}
trap log2syslog DEBUG

Simpan dan keluar /etc/profile

Ubah /etc/rsyslog.conf dan tambahkan baris berikut ke bagian bawah file:

# command line audit logging
local1.* -/var/log/cmdline

Save dan keluar /etc/rsyslog.conf

Restart service rsyslog, atau mulai ulang seluruh mesin untuk agar bisa memuat ulang bash profil dan memberlakukan perubahan.

/etc/init.d/rsyslog restart

Logging audit akan terlihat di bawah /var/log/syslog dan /var/log/cmdline.

cat /var/log/syslog
cat /var/log/cmdline 
sudo tail -f /var/log/syslog
sudo tail -f /var/log/cmdline

akan terlihat seperti ini:

Aug 22 15:04:39 ip-10-10-34-56 bash[15856]: jsmith:
Aug 22 15:04:40 ip-10-10-34-56 bash[15859]: jsmith:#011 sudo su -
Aug 22 15:04:43 ip-10-10-34-56 bash[15893]: root:
Aug 22 15:04:49 ip-10-10-34-56 bash[15903]: root:#011 ls -lart /var/log
Aug 22 15:05:01 ip-10-10-34-56 CRON[15927]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)
Aug 22 15:05:06 ip-10-10-34-56 bash[15937]: root:#011 ls -lart /var/log | grep cmd
Aug 22 15:15:01 ip-10-10-34-56 CRON[17254]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)
Aug 22 15:17:01 ip-10-10-34-56 CRON[17513]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)
Aug 22 15:20:02 ip-10-10-34-56 bash[17921]: root:#011 cd /var/log
Aug 22 15:20:03 ip-10-10-34-56 bash[17924]: root:#011 ls
Aug 22 15:20:16 ip-10-10-34-56 bash[17969]: root:#011 service confluence restart
Aug 22 15:20:16 ip-10-10-34-56 systemd[1]: Stopping SYSV: Confluence...
Aug 22 15:20:16 ip-10-10-34-56 confluence[17975]: Stopping confluence
Aug 22 15:20:16 ip-10-10-34-56 systemd[1]: Started Session c8 of user confluence.
Aug 22 15:20:27 ip-10-10-34-56 confluence[17975]: confluence stopped successfully
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Stopped SYSV: Confluence.
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Starting SYSV: Confluence...
Aug 22 15:20:27 ip-10-10-34-56 confluence[18103]: Starting confluence
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Stopping User Manager for UID 1300...
Aug 22 15:20:27 ip-10-10-34-56 systemd[20231]: Stopped target Default.
Aug 22 15:20:27 ip-10-10-34-56 systemd[20231]: Stopped target Basic System.
Aug 22 15:20:27 ip-10-10-34-56 systemd[20231]: Stopped target Paths.
Aug 22 15:20:27 ip-10-10-34-56 systemd[20231]: Stopped target Timers.
Aug 22 15:20:27 ip-10-10-34-56 systemd[20231]: Reached target Shutdown.
Aug 22 15:20:27 ip-10-10-34-56 systemd[20231]: Starting Exit the Session...
Aug 22 15:20:27 ip-10-10-34-56 systemd[20231]: Stopped target Sockets.
Aug 22 15:20:27 ip-10-10-34-56 systemd[20231]: Received SIGRTMIN+24 from PID 18107 (kill).
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Stopped User Manager for UID 1300.
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Removed slice User Slice of confluence.
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Created slice User Slice of confluence.
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Starting User Manager for UID 1300...
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Started Session c9 of user confluence.
Aug 22 15:20:27 ip-10-10-34-56 systemd[18113]: Reached target Paths.
Aug 22 15:20:27 ip-10-10-34-56 systemd[18113]: Reached target Timers.
Aug 22 15:20:27 ip-10-10-34-56 systemd[18113]: Reached target Sockets.
Aug 22 15:20:27 ip-10-10-34-56 systemd[18113]: Reached target Basic System.
Aug 22 15:20:27 ip-10-10-34-56 systemd[18113]: Reached target Default.
Aug 22 15:20:27 ip-10-10-34-56 systemd[18113]: Startup finished in 9ms.
Aug 22 15:20:27 ip-10-10-34-56 systemd[1]: Started User Manager for UID 1300.
Aug 22 15:20:28 ip-10-10-34-56 systemd[1]: Started SYSV: Confluence.
Aug 22 15:20:41 ip-10-10-34-56 bash[18207]: root:#011 ls
Aug 22 15:20:54 ip-10-10-34-56 bash[18271]: root:#011 less syslog

Anda dapat menyimpan log pada NFS dan atau log syslog ke komputer lain.

Optional (simpan env di ~/.bashrc):

PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -t "$USER[$$] $SSH_CONNECTION")'

[METODE 1] – alternative via rsyslog service

Untuk menggunakan rsyslog untuk mencatat setiap perintah Shell, cukup ikuti langkah-langkah di bawah ini:

  1. Buat file konfigurasi rsyslog baru, dan tentukan jalur file log. Misalnya: /var/log/commands.log

    vi /etc/rsyslog.d/bash.conf local6.* /var/log/commands.log

  2. Edit file ~/bashrc. Catatan: Anda perlu mengedit setiap pengguna ~/bashrc siapa pun yang membutuhkan log tersebut. vi ~/.bashrc whoami=”$(whoami)@$(echo $SSH_CONNECTION | awk ‘{print $1}’)” export PROMPT_COMMAND=’RETRN_VAL=$?;logger -p local6.debug “$whoami [$$]: $(history 1 | sed “s/^[ ][0-9]+[ ]//” ) [$RETRN_VAL]”’

Contoh : cat ~/.bashrc | tail -n2

whoami="$(whoami)@$(echo $SSH_CONNECTION | awk '{print $1}')"
export PROMPT_COMMAND='RETRN_VAL=$?;logger -p local6.debug "$whoami [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" ) [$RETRN_VAL]"'
  1. Restart rsyslog service systemctl restart rsyslog

Semua selesai. Lihat contoh format log di bawah ini:

date
Thu Apr 9 00:26:11 EDT 2020

cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.9 (Maipo)

tail -2 /var/log/commands.log
Apr 9 00:26:11 hostname root: root@x.x.x.x [1643]: date [0]
Apr 9 00:26:18 hostname root: root@x.x.x.x [1643]: cat /etc/redhat-release [0]

[METODE 2] – via bash shell option

  1. Tambahkan ‘shopt -s syslog_history’ ke seluruh sistem startup /etc/profile atau file inisialisasi pribadi ~/.bash_profile. Misalnya:

    cat /etc/profile | grep shopt shopt -s syslog_history

  2. Logout dan login lagi untuk melihat perubahan opsi ini.

  3. Log example: pwd /root date Thu Apr 9 01:26:46 EDT 2020

  4. Lihat log tail -2 /var/log/messages

    Apr 9 01:26:46 hostname -bash: HISTORY: PID=1345 UID=0 date Apr 9 01:26:52 hostname -bash: HISTORY: PID=1345 UID=0 tail -2 /var/log/messages

  5. Lihat live log

    tail -f /var/log/messages

    Apr 9 01:26:45 hostname -bash: HISTORY: PID=1345 UID=0 pwd Apr 9 01:26:46 hostname -bash: HISTORY: PID=1345 UID=0 date Apr 9 01:26:52 hostname -bash: HISTORY: PID=1345 UID=0 tail -2 /var/log/messages

[METODE 3] – via script command

Selain itu, jika Anda hanya ingin mencatat satu sesi terminal, coba saja perintah ‘skrip’ seperti di bawah ini, juga mudah digunakan dan sangat membantu.

  1. untuk memasang logging, jalankan:

    script /tmp/screen.log

  2. Sekarang Anda dapat memulai perintah bash Anda. Setelah selesai, Anda dapat keluar:

    exit

Ini kemudian akan menyimpan semua sesi ke file /tmp/screen.log

  1. Verifikasi output: cat /tmp/screen.log

Contoh :

script /tmp/screen.log
Script started, file is /tmp/screen.log

date
Thu Apr 9 00:28:26 EDT 2020

whoami
root

exit

Script done, file is /tmp/screen.log

cat /tmp/screen.log
Script started on Thu 09 Apr 2020 12:28:23 AM EDT
date
Thu Apr 9 00:28:26 EDT 2020
whoami
root
exit
exit
Script done on Thu 09 Apr 2020 12:28:42 AM EDT

riwayat baris perintah yang lebih friendly, lebih banyak perintah yang disimpan, agregat, tambahkan informasi datetime.

tambahkan di /etc/profile

# lihat format 'tanggal' untuk format waktu lainnya

shopt -s histappend
HISTSIZE=10000
HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "
HISTCONTROL=ignoredups
PROMPT_COMMAND="history -a;history -c;history -r;$PROMPT_COMMAND"

exit & save lalu test setelah login ssh :

history | less