Tuesday, September 30, 2025

How to fix error HY000/1045 after upgrading phpmyadmin

I used Debian 13 repository to upgrade phpmyadmin. During upgrading from previous version, configuration can not be continue and must be ignore. After phpmyadmin installed error messages come to web:

  • mysqli::real_connect(): (HY000/1045): Access denied for user 'phpmyadmin'@'localhost' (using password: YES) 
  • Connection for controluser as defined in your configuration failed.

Create user pma (default) and password:

MariaDB [(none)]> CREATE USER 'pma'@'localhost' IDENTIFIED BY 'pmapass';
Query OK, 0 rows affected (0.003 sec)

MariaDB [(none)]> GRANT ALL PRIVILEGES ON phpmyadmin.* TO 'pma'@'localhost';
Query OK, 0 rows affected (0.003 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.002 sec)

Edit file /etc/phpmyadmin/config-db.php

...
$dbuser='pma';
$dbpass='pmapass';
...

Edit file /etc/phpmyadmin/config.inc.php

...
/* Configure according to dbconfig-common if enabled */
if (!empty($dbname)) {
    /* Authentication type */
    $cfg['Servers'][$i]['auth_type'] = 'cookie';
    /* Server parameters */
    if (empty($dbserver)) $dbserver = 'localhost';
    $cfg['Servers'][$i]['host'] = $dbserver;

    if (!empty($dbport) || $dbserver != 'localhost') {
        $cfg['Servers'][$i]['connect_type'] = 'tcp';
        $cfg['Servers'][$i]['port'] = $dbport;
    }
    //$cfg['Servers'][$i]['compress'] = false;
    /* Optional: User for advanced features */
    $cfg['Servers'][$i]['controluser'] = $dbuser;
    $cfg['Servers'][$i]['controlpass'] = $dbpass;
    /* Optional: Advanced phpMyAdmin features */
    $cfg['Servers'][$i]['pmadb'] = $dbname;
    $cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
    $cfg['Servers'][$i]['relation'] = 'pma__relation';
    $cfg['Servers'][$i]['table_info'] = 'pma__table_info';
    $cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
    $cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
    $cfg['Servers'][$i]['column_info'] = 'pma__column_info';
    $cfg['Servers'][$i]['history'] = 'pma__history';
    $cfg['Servers'][$i]['table_uiprefs'] = 'pma__table_uiprefs';
    $cfg['Servers'][$i]['tracking'] = 'pma__tracking';
    $cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
    $cfg['Servers'][$i]['recent'] = 'pma__recent';
    $cfg['Servers'][$i]['favorite'] = 'pma__favorite';
    $cfg['Servers'][$i]['users'] = 'pma__users';
    $cfg['Servers'][$i]['usergroups'] = 'pma__usergroups';
    $cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
    $cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches';
    $cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
    $cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
    $cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';

    /* Uncomment the following to enable logging in to passwordless accounts,
     * after taking note of the associated security risks. */
    // $cfg['Servers'][$i]['AllowNoPassword'] = TRUE;

    /* Advance to next server for rest of config */
    $i++;
}

/* Authentication type */
//$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
//$cfg['Servers'][$i]['host'] = 'localhost';
//$cfg['Servers'][$i]['connect_type'] = 'tcp';
//$cfg['Servers'][$i]['compress'] = false;
/* Uncomment the following to enable logging in to passwordless accounts,
 * after taking note of the associated security risks. */
// $cfg['Servers'][$i]['AllowNoPassword'] = TRUE;

/**
 * phpMyAdmin configuration storage settings.
 */

/* User used to manipulate with storage */
$cfg['Servers'][$i]['controlhost'] = '';
$cfg['Servers'][$i]['controlport'] = '';
$cfg['Servers'][$i]['controluser'] = 'pma';
$cfg['Servers'][$i]['controlpass'] = 'pmapass';

/* Storage database and tables */
$cfg['Servers'][$i]['pmadb'] = 'phpmyadmin';
$cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
$cfg['Servers'][$i]['relation'] = 'pma__relation';
$cfg['Servers'][$i]['table_info'] = 'pma__table_info';
$cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
$cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
$cfg['Servers'][$i]['column_info'] = 'pma__column_info';
$cfg['Servers'][$i]['history'] = 'pma__history';
$cfg['Servers'][$i]['table_uiprefs'] = 'pma__table_uiprefs';
$cfg['Servers'][$i]['tracking'] = 'pma__tracking';
$cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
$cfg['Servers'][$i]['recent'] = 'pma__recent';
$cfg['Servers'][$i]['favorite'] = 'pma__favorite';
$cfg['Servers'][$i]['users'] = 'pma__users';
$cfg['Servers'][$i]['usergroups'] = 'pma__usergroups';
$cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
$cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches';
$cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
$cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
$cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';
...

 

Debian 13: how to limit cpu frequency to preserve power or keep cpu cooler

Since Debian 13, cpufreq is being replaced by cpupower. Don't mix using power-profiles-daemon and linux-cpupower. I prefer to use linux-cpupower.

Install 

# apt-get install linux-cpupower

Show available frequency

# cpupower frequency-info
analyzing CPU 1:
  driver: acpi-cpufreq
  CPUs which run at the same hardware frequency: 1
  CPUs which need to have their frequency coordinated by software: 1
  maximum transition latency: 4.0 us
  hardware limits: 1000 MHz - 2.20 GHz
  available frequency steps:  2.20 GHz, 2.00 GHz, 1.80 GHz, 1.60 GHz, 1.30 GHz, 1000 MHz
  available cpufreq governors: performance schedutil
  current policy: frequency should be within 1000 MHz and 2.20 GHz.
                  The governor "schedutil" may decide which speed to use
                  within this range.
  current CPU frequency: 1.30 GHz (asserted by call to hardware)
  boost state support:
    Supported: yes
    Active: no
    Boost States: 2
    Total States: 8
    Pstate-Pb0: 2500MHz (boost state)
    Pstate-Pb1: 2400MHz (boost state)
    Pstate-P0:  2200MHz
    Pstate-P1:  2000MHz
    Pstate-P2:  1800MHz
    Pstate-P3:  1600MHz
    Pstate-P4:  1300MHz
    Pstate-P5:  1000MHz

Available frequency steps are:  2.20 GHz, 2.00 GHz, 1.80 GHz, 1.60 GHz, 1.30 GHz, 1000 MHz. Use frequency 1.8 GHz for all core:

# cpupower frequency-set -u 1.80 GHz
Setting cpu: 0
Setting cpu: 1
Setting cpu: 2
Setting cpu: 3

After applying maximum frequency

# cpupower frequency-info
analyzing CPU 2:
  driver: acpi-cpufreq
  CPUs which run at the same hardware frequency: 2
  CPUs which need to have their frequency coordinated by software: 2
  maximum transition latency: 4.0 us
  hardware limits: 1000 MHz - 2.20 GHz
  available frequency steps:  2.20 GHz, 2.00 GHz, 1.80 GHz, 1.60 GHz, 1.30 GHz, 1000 MHz
  available cpufreq governors: performance schedutil
  current policy: frequency should be within 1000 MHz and 1000 MHz.
                  The governor "schedutil" may decide which speed to use
                  within this range.
  current CPU frequency: 1000 MHz (asserted by call to hardware)
  boost state support:
    Supported: yes
    Active: no
    Boost States: 2
    Total States: 8
    Pstate-Pb0: 2500MHz (boost state)
    Pstate-Pb1: 2400MHz (boost state)
    Pstate-P0:  2200MHz
    Pstate-P1:  2000MHz
    Pstate-P2:  1800MHz
    Pstate-P3:  1600MHz
    Pstate-P4:  1300MHz
    Pstate-P5:  1000MHz

To make it persistent, create or edit /etc/systemd/system/cpu-limit.service

[Unit]
Description=Set CPU power management settings
# latest state runlevel 3 in SysVinit, let CPU run maximum frequency during starting system services
After=multi-user.target
# run after network ready
#After=network.target
# network may not run
#After=sysinit.target

[Service]
Type=oneshot
ExecStart=/usr/bin/cpupower frequency-set -u 2.00GHz
#ExecStart=/usr/bin/cpupower frequency-set --max 2.00GHz
#ExecStart=/usr/bin/cpupower frequency-set -g performance
# You can customize the cpupower command here.
# For example, to set to powersave:
# ExecStart=/usr/bin/cpupower frequency-set -g powersave
# Or to set a specific frequency:
# ExecStart=/usr/bin/cpupower frequency-set -f 2.5GHz

[Install]
WantedBy=multi-user.target

Note: you can copy paste and adjust frequency for your laptop/PC.

Change file permission

# chmod 644 /etc/systemd/system/cpu-limit.service

Reload system daemon

# systemctl daemon-reload
# systemctl enable cpu-limit.service
Created symlink '/etc/systemd/system/multi-user.target.wants/cpu-limit.service' → '/etc/systemd/system/cpu-limit.service'.

Everytime your restart this daemon will run time to set maximum frequency.

 

 

Sunday, September 28, 2025

Debian 13: Fresh install dual boot Axioo Hype 5 AMD X6 using usb flash disk with ventoy boot manager installed

Spesification Axioo Hype 5 AMD X6:

  • Ryzen™ 5 6600H & grafis Radeon™ 660M
  • 16GB DDR5 RAM & 512GB SSD Gen 3

Shrink your windows 11 partition. We need 84 GB free space. 80 GB for debian / ext4 and 4 GB for swap. We do need to reserve 500 MB for ESP (EFI System Partition), windows 11 already create it.

Use windows disk manager and shrink partition. Fill

Enter the amount of space in MB 84000 MB

It is good practice to separate partition for windows system and application, and user data partition.

To install Ventoy boot manager in flash disk follow this.

Insert your USB flash disk contain Debian 13 net installer and ventoy installed. Press and hold “Shift” and restart windows. Unpress shift after laptop restarted.

Select “Use Device” and choose USB flash disk to boot.

Ventoy boot manager will give you any iso file you stored on flash disk if any. Choose debian, select “Boot in normal mode”.

Debian installer started, follow the instruction. You need an internet connection to install the xfce desktop environment. 

At the partition section, choose “Manual”. Create 80 GB type “ext4” mount / and 4 GB type “Swap”. Write change to disk.

Beware, there is a USB flash disk appear in the partition menu. It is shown as “SCSI1 (0.0.0) (sda)” on my laptop.

In package manager, I choose 

  • Xfce
  • Standard system utility

For special purpose installation choose debian blend. Release of debian pure blend can be read on www.debian.org/blends/.

Finally, restart your laptop. Press F2 to enter bios. At boot menu, select debian boot manager first and then windows. Debian grub has the option to enter windows not vice versa.

If you wish, to select windows as default grub selection, edit /etc/default/grub

GRUB_DEFAULT=2

Save it and run

# update-grub

Friday, September 26, 2025

Debian 13: Using Ventoy to create bootable flash disk for multiple ISO

Download ventoy from www.ventoy.net, choose tar.gz. At this documentation wrote, it was ventoy-1.1.07-linux.tar.gz.

Extract it here, it will create directory ventoy-1.1.07. You can move directory from download to your home.

To avoid any typo or wrong device storage, it is recommended to use GUI. Insert you new or unused flash disk and open ventoy GUI, from terminal

$ cd ventoy-1.1.07/
$ ./VentoyGUI.x86_64&

It will ask root/sudo password. Click Install and you will get warning all data will be destroyed and flash disk will be formatted. Wait until finish.

Unmount your flash disk. Remove and reinsert your flash disk. You can add your iso file into your flash disk.

Note: Do not store your iso files too deep under subdirectory. 

Sample Directory:

Ventoy
-- debian
   -- debian-13.1.0-amd64-netinst.iso
-- windows
   -- 

Note:  size of debian-13.1.0-amd64-netinst.iso is more then 700MB which it is not fit into CD ROM anymore.

Use flash disk USB 3.0 or above. I use Adata flash disk USB 3.0.

It is hard to find CD or DVD in Indonesia.  Almost software is distribute directly from cloud, no disk media anymore. Some provide flash disk installer in part of package.

 

 

Saturday, September 20, 2025

Debian 13: solving error ring 2 stalled on HP 15-AF109AX AMD A8-7410 APU Radeon R5

Laptop:

AMD A8-7410 APU Radeon R5 GCN 1.2 (Spectre)
HP 15-AF109AX 

symptom: Screen flickering continuously at some interval  time

Dmesg error:

[ 3806.507278] radeon 0000:00:01.0: ring 2 stalled for more than 29348msec
[ 3806.507310] radeon 0000:00:01.0: GPU lockup (current fence id 0x000000000000038f last fence id 0x0000000000000390 on ring 2)

Which non free firmware? These are generation AMD Graphics Processor

Use radeon for older then GCN and RDNA

Use amdgpu for Graphic Core Next/GCN generation

  1. GCN 1.0 Radion HD 7000
  2. GCN 2.0 Radeon 200
  3. GCN 3.0 Radeon 300
  4. GCN 4.0 Radeon 400/500/600
  5. GCN 5.0 Radeon RX Vega, Radeon VII

Use  ROCm for RDNA

  1. RDNA 1 Radeon RX 5000
  2. RDNA 2 Radeon RX 6000
  3. RDNA 3 Radeon RX 7000
  4. RDNA 4 Radeon RX 8000 

Install firmware, you need add non-free repository

# apt-get install firmware-amd-graphics  

Check firmware loaded

# lspci -k | grep -A 3 VGA
00:01.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Mullins [Radeon R4/R5 Graphics] (rev 45)
    Subsystem: Hewlett-Packard Company Device 80cc
    Kernel driver in use: radeon
    Kernel modules: radeon, amdgpu

or

# lspci -nn | grep VGA

The Mullins Accelerated Processing Units (APUs), which include the Radeon R4/R5 Graphics, use the GCN 1.1 architecture.  Googling for yours if necessary. Create/Edit /etc/X11/xorg.conf.d/20-radeon.conf 

Section "Device"
    Identifier "AMD Graphics"
    Driver "amdgpu"
    Option "TearFree" "true"
EndSection

If your card is GCN 1.0 and 1.2 ("Southern Islands" or "Sea Islands" cards) , for potentially better performance and Vulkan support, you need to add kernel parameter. Edit /etc/default/grub and add parameter

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash radeon.cik_support=0 amdgpu.cik_support=1"

update grub

# update-grub update-grub

Example old AMD Graphic

  • Wrestler [Radeon HD 6310] 

google-chrome use gpu acceleration, this can also causing ring 2 stalled. Disabling google-chrome gpu accelerated.

$ google-chrome-stable --disable-gpu --disable-software-rasterizer

Create script to run start_chrome.sh

#!/bin/bash
google-chrome-stable --disable-gpu --disable-software-rasterizer "$@" &

Make it runnable

$ chmod 764 ./start_chrome.sh

 

Friday, September 19, 2025

Debian 13: using systemd-resolved to replace old way to resolving dns

Install systemd-resolved 

# apt-get install  systemd-resolved

Enable it

# systemctl enable systemd-resolved

Old fashion /etc/resolv.conf 

# Generated by NetworkManager
nameserver 45.90.28.186
nameserver 8.8.8.8
nameserver 1.1.1.1

Change/Edit configuration file /etc/systemd/resolved.conf 

DNS=45.90.28.186 8.8.8.8 1.1.1.1
DNSOverTLS=yes

Optional

DNS=45.90.28.186 8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2006:4700:4700::1111#cloudflare-dns.com 2606:4700:4700:1001#cloudflare-dns.com
DNSOverTLS=yes 

Enable systemd-resolved in Network Manager, edit /etc/NetworkManager/NetworkManager.conf 

[main]
plugins=ifupdown,keyfile
dns=systed-resovled

Restart Network Manager

# systemctl restart NetworkManager

Restart systemd-resolved

# systemctl restart systemd-resolved

Test it

# nslookup duckduckgo.com
Server:        127.0.0.53
Address:    127.0.0.53#53

Non-authoritative answer:
Name:    duckduckgo.com
Address: 20.43.161.105

Done. This configuration can be used to protect your dns resolved from dns query hijacking. 

Handy diagnostics guide:  

Dig

# dig duckduckgo.com @1.1.1.1 +short
safe.duckduckgo.com.
202.169.44.80

Nslookup

# nslookup duckduckgo.com 8.8.8.8
Server:        8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
duckduckgo.com    canonical name = safe.duckduckgo.com.
Name:    safe.duckduckgo.com
Address: 202.169.44.80
Name:    safe.duckduckgo.com
Address: 2404:8000:11:2::2 

Whois

# whois 202.168.44.80 
% [whois.apnic.net]
% Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html

% Information related to '202.168.0.0 - 202.168.63.255'

% Abuse contact for '202.168.0.0 - 202.168.63.255' is 'hostmaster@tpgtelecom.com.au'

inetnum:        202.168.0.0 - 202.168.63.255
netname:        TPG-AU
descr:          TPG Internet Pty Ltd.
country:        AU
org:            ORG-TIPL2-AP
admin-c:        TH178-AP
tech-c:         TH178-AP
abuse-c:        AT937-AP
status:         ALLOCATED PORTABLE
remarks:        Australian Internet Service Provider (ISP)
remarks:        http://www.tpg.com.au

Curl

# curl -I https://www.duckduckgo.com
curl: (7) Failed to connect to www.duckduckgo.com port 443 after 4129 ms: Could not connect to server

Note: curl and whois showing duckduckgo.com directing to wrong address.

Tuesday, September 16, 2025

Debian 13: UEFI partition during installation process

Begin in 2011, computer manufacturers were moving to use UEFI and left BIOS. Today, it is mandatory for system with UEFI to have separate partition for EFI System Partition / ESP. 

ESP contain boot loader to start operating system. One ESP may contain some boot loader for different operating system. Size of ESP for windows and Debian is 500MB to avoid problem when update occurred. It means for multi OS with different boot loader, ESP partition required bigger size.

During Debian installation, at step configure partition, create:

  • size: 500 MB or bigger
  • type: "EFI System Partition (ESP)", "EFI System Partition" or similar

All partitions required in Debian 13 system are:

  1. ESP: 500MB or bigger, will marked boot sector 0xEE
  2. Swap: 2 times physical memory. IMO, for physical memory more then 16GB, swap size equal to physical memory or less.
  3. root partition for single point mount /, or custom partition.

There are 3 types boot process and its year period:

  1. BIOS: old PC
  2. BIOS + GPT PC 2000-2020 
  3. ESP + GPT PC > 2020 

Monday, September 15, 2025

Python: using gemini and chatgpt to help creating python3 code to get last 3 characters in composite name in Sheet1

We define the problem to ask AI to generate python code. This is the crucial part, to get output that we expected.

In Indonesia language we define:

saya punya data excel di sheet1 yang berisi nama.
headet sheet1 adalah no dan nama komposit.
nama komposit terdiri dari 2 nama dipisah dengan tanda /.
tidak semua nama komposit memiliki 2 nama.
nama pertama ada yang menggunakan nama panggilan yang disimpan didalam tanda ().
nama pertama selalu ada disetiap row.
sayang ingin mengambil 3 huruf terakhir dari nama pertama, bukan yang berada dalam tanda kurung.
buatkan kode pyhton3 dengan openpyxl library.
print no, nama, dan 3 huruf terakhir, gunakan ; untuk pemisah dan masukan string kedalam "" agar output mudah di simpan kedalam csv.

In English language we define:

I have Excel data in sheet 1 containing names.
The header of sheet 1 is a composite number and name.
A composite name consists of two names separated by a / symbol.
Not all composite names have two names.
Some first names use nicknames stored within the () symbol.
The first name is always present in every row.
Unfortunately, I want to extract the last three letters of the first name, not the ones in parentheses.
Create a Python 3 code using the OpenPyXL library.
Print the number, name, and last three letters, use ; as the separator, and enclose the string in "" to make the output easy to save to a CSV.

Choose one of them, feed it into chat.openai.com / chatgpt.com and gemini.google.com, you can use 2 tab or 2 window browser. This is only example, you need to define your expected output.

I replace xlsx file name "data_tr.xlsx"

Here is the code generated by chatgpt.com:

from openpyxl import load_workbook
import re

# Mengambil nama pertama dari "nama komposit" (sebelum tanda /)
# Menghapus bagian dalam tanda kurung () dari nama pertama
# Mengambil 3 huruf terakhir dari nama pertama yang telah dibersihkan

# Ganti dengan path ke file Excel kamu
file_path = "data_tr.xlsx"

# Load workbook dan sheet
wb = load_workbook(filename=file_path)
ws = wb["Sheet1"]

# Print header
print('"no";"nama komposit";"3 huruf terakhir"')

# Proses tiap baris (mulai dari baris ke-2 karena baris 1 adalah header)
for row in ws.iter_rows(min_row=2, max_col=2):
    no = row[0].value
    nama_komposit = str(row[1].value).strip() if row[1].value else ""

    # Ambil nama pertama dari nama komposit
    nama_pertama = nama_komposit.split("/")[0].strip()

    # Hapus isi dalam tanda kurung, misalnya (Budi)
    nama_pertama_bersih = re.sub(r"\([^)]*\)", "", nama_pertama).strip()

    # Ambil 3 huruf terakhir (jika cukup panjang)
    tiga_huruf_terakhir = nama_pertama_bersih[-3:] if len(nama_pertama_bersih) >= 3 else nama_pertama_bersih

    # Format dan cetak hasil
    print(f'"{no}";"{nama_komposit}";"{tiga_huruf_terakhir}"')

Here is the code generated by gemini:

import openpyxl

# Ganti 'nama_file_anda.xlsx' dengan nama file Excel Anda
file_path = 'data_tr.xlsx'

try:
    # Membuka workbook dan memilih sheet aktif
    workbook = openpyxl.load_workbook(file_path)
    sheet = workbook.active

    # Mencetak header
    header_string = '"No";"Nama Komposit";"3 Huruf Terakhir"'
    print(header_string)

    # Iterasi dari baris ke-2 (mengabaikan header yang sudah dicetak)
    for row in sheet.iter_rows(min_row=2):
        no_cell = row[0]
        nama_komposit_cell = row[1]
        
        # Mengabaikan baris kosong
        if not no_cell.value or not nama_komposit_cell.value:
            continue

        # Mengambil nilai dari cell
        no = no_cell.value
        nama_komposit = str(nama_komposit_cell.value)
        
        # Memisahkan nama komposit berdasarkan '/'
        nama_pertama = nama_komposit.split('/')[0].strip()
        
        # Menghapus nama panggilan dalam kurung
        if '(' in nama_pertama and ')' in nama_pertama:
            idx_buka = nama_pertama.find('(')
            nama_pertama = nama_pertama[:idx_buka].strip()
            
        # Mengambil 3 huruf terakhir dari nama pertama dan mengubahnya menjadi huruf kapital
        tiga_huruf_terakhir = nama_pertama[-3:].upper()
        
        # Mencetak data sesuai format yang diminta
        output_string = f'"{no}";"{nama_komposit}";"{tiga_huruf_terakhir}"'
        print(output_string)

except FileNotFoundError:
    print(f"Error: File '{file_path}' tidak ditemukan. Pastikan nama file sudah benar.")
except Exception as e:
    print(f"Terjadi kesalahan: {e}")

The code contain Indonesia Languge when the chat feed in Indonesia Language.

If you use virtual environment, activate it first

$ cd mypyenv
~/mypyenv$ source venv/bin/activate

Remember, AI may make mistake the output was generated base on statistics  values from every tokens. You must check the output. You may seen the output style has deference based on data the AI developer feed during learning.

This is the way AI help to create source code that we never learn before.

Tuesday, September 9, 2025

Python: fixing indentation in python

In python, indentation must consistent, runtime will report error if indentation inconsistent. 

It is hard if we use some editor to write the code. We can use black to fix it automatically base on pep 8 (Python Enhancement Proposal  8).

Installing black

# apt-get install black
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  python3-click python3-mypy-extensions python3-pathspec python3-platformdirs
Suggested packages:
  python-black-doc
The following NEW packages will be installed:
  black python3-click python3-mypy-extensions python3-pathspec
  python3-platformdirs
0 upgraded, 5 newly installed, 0 to remove and 1 not upgraded.
Need to get 1,502 kB of archives.
After this operation, 6,442 kB of additional disk space will be used.

Using black

$ black ./[your_python_file_to_fix].py
reformatted [your_python_file_to_fix].py

All done! ✨ 🍰 ✨
1 file reformatted.

Wednesday, September 3, 2025

Debian 13: troubleshooting connecting to wifi using cmd nmcli

I prefer to use command line because mostly server does not  installed window manager. I need to familiar to use command line in any situation.

To show wifi radio enable

# nmcli radio wifi
enabled

To turn on radio wifi

# nmcli radio wifi on

To list available wifi

# nmcli device wifi list
IN-USE  BSSID              SSID   
...

To rescan available wifi

# nmcli dev wifi rescan

To connect to wifi access point

# nmcli device wifi connect "[your_SSID]" password "[your_password]"
...

To show connection

# nmcli connection show
NAME                UUID                                  TYPE      DEVICE
...

Note: parameter dev is short from device

Tuesday, September 2, 2025

Debian 13 icewm/openbox/fluxbox: using pavucontrol & pulseaudio

 Install pavucontrol & pulseaudio

# apt-get install pavucontrol pulseaudio
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
...

To run pavecontrol in terminal

$ pulseaudio&


Monday, September 1, 2025

pyhton3: read xlsx using open3pyxl

Install open3pyxl library on Debian system

# apt-get install open3pyxl
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
...

Install open3pyxl library on user virtual environment (not messing with python used by Debian)

$ cd mypyenv
~/mypyenv$ source venv/bin/activate
(venv) [user]@[hostname]:~/mypyenv$ pip list
Package Version
------- -------
pip     25.1.1
(venv) [user]@[hostname]:~/mypyenv$ pip install openpyxl
Collecting openpyxl
  Downloading openpyxl-3.1.5-py2.py3-none-any.whl.metadata (2.5 kB)
Collecting et-xmlfile (from openpyxl)
  Downloading et_xmlfile-2.0.0-py3-none-any.whl.metadata (2.7 kB)
Downloading openpyxl-3.1.5-py2.py3-none-any.whl (250 kB)
Downloading et_xmlfile-2.0.0-py3-none-any.whl (18 kB)
Installing collected packages: et-xmlfile, openpyxl
Successfully installed et-xmlfile-2.0.0 openpyxl-3.1.5

(venv) [user]@[hostname]:~/mypyenv$ pip list
Package    Version
---------- -------
et_xmlfile 2.0.0
openpyxl   3.1.5
pip        25.1.1

Here is sample script to enumerate row and column

import openpyxl
from datetime import datetime

path = "./[replace_with_your_file].xlsx"

# wb_obj = openpyxl.load_workbook(path) # Open xlsx without option
wb_obj = openpyxl.load_workbook(path, data_only=True) # Open xlsx with option Data Only

## object sheet
# using active sheet
#sheet_obj = wb_obj.active
## using Sheet1
sheet_obj = wb_obj["Sheet1"]

# Sheet start from 1,1 not 0,0
# Access cell at row 1, column 1
#cell_obj = sheet_obj.cell(row=1, column=1)
#print("Cell 1 column 1 is ",cell_obj.value)

# to print row 1 column 20
#cell_obj = sheet_obj.cell(row=1, column=20)
#print("Cell 1 column 20 is ",cell_obj.value)

# Enumerate row
# first row is header
# max_row may contains empty row
for i in range (2, sheet_obj.max_row):
    cell_obj = sheet_obj.cell(row=i, column=1)
    if cell_obj.value is not None:
        # enumerate column
        # we need fix column e.q 6 column from 1 to 6
        # Do not use max_column
        # for j in range (1, max_column): # Do not use this, use fix number
        for j in range (1, 6):
            mycell_obj = sheet_obj.cell(row=i, column=j)
            #if mycell_obj is not None: # if you use
max_column, this will not working, only working for row
            print(mycell_obj.value, " | ", end='') # print without new line
        print() # print a new line
    else:
        # the row is empty we break
        print() # print a new line
        break