ls 的 quoting-style

有人來問才知道 ls 是有在改版的。

在 coreutils 8.30 (RHEL8) 預設的 quoting-style 是 shell,在 coreutils 8.22 (RHEL7) 預設的 quoting-style 是 literal,主要差異是在於檔名有空白時是否要加上單引號。

在 coreutils 8.30 (RHEL8) 是這樣

# ls -l
total 8
-rw-r--r--. 1 root root   0 Dec  1 14:38  bar.txt
-rw-r--r--. 1 root root 514 Dec  1 15:38  cluster-logging.yml
-rw-r--r--. 1 root root   0 Dec  1 14:38 'foo bar.txt'
-rw-r--r--. 1 root root   0 Dec  1 14:38  foo.txt
-rw-r--r--. 1 root root 528 Dec  1 15:38  openshift-user-critical.yml

在 coreutils 8.22 (RHEL7) 是這樣

# ls -l
總計 0
-rw-r--r--. 1 root root 0 12月  1 14:41 bar.txt
-rw-r--r--. 1 root root 0 12月  1 14:41 foo bar.txt
-rw-r--r--. 1 root root 0 12月  1 14:41 foo.txt

在 RHEL8 想讓輸出的結果跟 RHEL7 一樣的話,可以加上 –quoting-style 參數

ls -l --quoting-style=literal

RHEL8強制解除註冊

前兩天遇到的狀況是這樣,公司裡的 RHEL8 主機是註冊到 Satellite 上,但 Satellite 主機因為機房設備升級,開不了機,可是這台 RHEL8 主機又急著要安裝套件,那就得先解除註冊。

第一步,是先處理 /etc/rhsm/rhsm.conf ,註冊到 Satellite 時,rhsm.conf 裡的設定會被修改,表明註冊到 Satellite。在這裡可以找到備份的 rhsm.conf ,把這檔案復原回去。

第二步,是移除套件,在註冊到 Satellite 時,會安裝一個套件,這個套件包含了註冊到 Satellite 的資訊以及憑證。套件的名稱裡有 katello-ca ,找到之後,用 rpm -e 或 yum remove 移除。

第三步,是移除 /etc/pki/consumer 跟 /etc/pki/entitlement ,這裡有 subscription-manager 註冊後取得的資訊。

rm -rf /etc/pki/consumer
rm -rf /etc/pki/entitlement
subscription-manager clean

處理完之後,就可以用 subscription-manager register 來註冊到 Red Hat 了。

參考資料

RHEL8 重置 root 密碼

因為查了第二次還第三次,所以紀錄下來。

步驟如下:

  1. 開機時,在 grub 開機選單畫面按上或下,避免自動進入預設項目開機,然後在第一個項目按下 e 來編輯。
  2. 在 linux 那一行的最後加入 rd.break 之後,按下 ctrl + x 繼續開機
  3. 接著會進入 console ,這時輸入下面指令
mount -o remount,rw /sysroot
chroot /sysroot
passwd
touch /.autorelabel
exit
exit

做到這邊,印象中會重開機或繼續開機程序,總之最後就完成了。

參考資料

如果你有 Red Hat developer account 的話,應該可以看到這篇:RESETING THE ROOT PASSWORD

centos2rhel

工作有需要幫客戶將 CentOS 轉換到 Red Hat Enterprise Linux,試驗了一下。這個轉換是有條件的,必須要滿足前置條件,才能順利做轉換。

我用的環境是 CentOS 8.3 ,用以下的 playbook 來安裝 Red Hat 所提供的 convert2rhel 工具,先新增檔案,命名為 install-convert2rhel.yml ,然後把下面的內容貼進去。

---
- name: Convert CentOS to RHEL
  hosts: all
  become: yes

  tasks:
    - name: Get GPG key
      get_url:
        url: https://www.redhat.com/security/data/fd431d51.txt
        dest: /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
        mode: '0440'

    - name: Get repo
      get_url:
        url: https://ftp.redhat.com/redhat/convert2rhel/8/convert2rhel.repo
        dest: /etc/yum.repos.d/convert2rhel.repo
        mode: '0440'

    - name: Get convert2rhel
      yum:
        name: convert2rhel
        state: latest

接著執行:ansible-playbook -i <your_ip>, -u root -k install-convert2rhel.yml

目的主機內就有 convert2rhel 指令了,先依照說明來執行看看

convert2rhel --username <redhat_account> --password <redhat_password> -a

執行結果會說需要把 CentOS 升級到 7.9 或是 8.4 才可以進行轉換,所以用 yum update -y 將 CentOS 8.3 升級到 8.4

升級完成,重新開機,再來執行一次。我這次是遇到 Python 處理編碼發生錯誤,改用

LANG=C convert2rhel --username <redhat_account> --password <redhat_password> -a

接著可以繼續往下了,依照指示回答問題以後,就順利轉換到 RHEL 了。(懶得回答可以加上 -y)

man convert2rhel 可以看到使用說明,講的還蠻清楚的。指令有提供了 –disablerepo / –enablerepo 可以關閉或啟用可能影響轉換的 repo,也可以使用 –no-rpm-va 來跳過檢查,也有提供 –activationkey 來支援 Red Hat Satellite,也可以使用 –no-rhsm 來避免註冊到 Red Hat 。

我自己是覺得使用這類的工具其實蠻需要經驗,如果主機上的軟體套件很單純的話,就還好,如果是有引用到第三方的 repo,可能就需要耐心來做狀況排除。同時,也需要事後的檢查,來確保上面的服務跟轉移前一樣。

Linux 改 hostname

目前大部分的 Linux 發行版應該都有 hostnamectl 指令了,用這個指令就可以去修改。

hostnamectl set-hostname <your-hostname>

昨天遇到一個怪狀況,怎麼改都改不了,請教 Google 大神以後,才知道 cloud-init 也有關係。

遇到這狀況,有兩個方法:

  1. 把 cloud-init 服務給關掉:systemctl disable cloud-init
  2. 修改 /etc/cloud/cloud.cfg ,把裡面的 preserve_hostname false 改為 preserve_hostname true

套用其中一種方法以後,重新開機,這樣就行了。

順便紀錄以下我以前怎麼改的,以前改要做這幾個步驟:

  1. 修改 /etc/hostname 這個檔案裡的內容
  2. 修改 /etc/hosts 裡的對應

改完以後,再重新開機。

如何在 multipass VM內執行 GUI 應用程式

multipass 是 Canonical 所推出的一個輕量級 VM 管理工具,它跨平台,支援 Linux、Windows 跟 MacOS。

這個工具用一陣子了,相當的好用,缺點是目前只有 Ubuntu 的 VM 可用。之前是想到,既然 multipass shell 是用 ssh 登入,那麼應該要可以 Forward X11 才對。也就是說以 SSH 登入以後,執行 GUI 應用程式,畫面會轉向到目前 Host 的 X Server 。

但試了以後卻不行,請教 Google 以後,Google 告訴我 StackOverflow 上已經有人解答了:18.04 – How to open GUI applications in multipass container(guest = ubuntu, host = ubuntu)? X-Forwarding – Ask Ubuntu

先說明一下我的環境:

  • Ubuntu 20.04
  • 用 snap 安裝 multipass

首先,先取得 ssh key,因為 multipass 是用 snap 安裝的,所以得從 /var/snap/multipass 裏面找到 ssh private key,把它複製到 ~/.ssh/multipassKey 目錄下。

    mkdir ~/.ssh/multipassKey
    sudo cp /var/snap/multipass/common/data/multipassd/ssh-keys/id_rsa ~/.ssh/multipassKey/id_rsa

接著變更這個 private key 的權限為 0600,並且變更擁有者

sudo chown user -R ~/.ssh/multipassKey
sudo chmod 0600 ~/.ssh/multipassKey/id_rsa

再來啟動 VM,並且察看 VM 的 IP

multipass start name
multipass ls

最後使用 ssh 登入

ssh -X -i ~/.ssh/multipassKey/id_rsa ubuntu@<my_vm_ip>

就這樣。

CPack

在 twitter 上看到有人推薦 RPiPlay 這個專案,這個開放原始碼軟體主要的用途是當作 AirPlay 伺服器。當這個軟體啟動時,MacOS 裝置跟 iOS 裝置會搜尋到啟動這個軟體的裝置,當選擇鏡射時,就可以將 MacOS 裝置或 iOS 裝置上的畫面投放過去。作者主要是用在 Raspberry Pi 上,但其實在一般的 Linux distribution 上也可以使用。

目前作者沒有打包任何的套件,因此要用,只能自行編譯、安裝。編譯方法蠻簡單的,因為我是用 ubuntu ,所以這邊只介紹 Ubuntu 上怎麼編譯。首先安裝編譯器跟 RPiPlay 會用到的函式庫標頭檔

sudo apt-get install cmake \
    libavahi-compat-libdnssd-dev \
    libplist-dev \
    libssl-dev

接著下載原始碼跟進行編譯

git clone https://github.com/FD-/RPiPlay.git
cd RPiPlay
mkdir build
cd build
cmake ..
make

等編譯完成後,再安裝

sudo make install

等等,講到這邊還沒提到 CPack 啊。

因為我喜歡儘量使用 package 來管理,所以就想到,這可以打包為 debian package 嗎?就找了資料,發現 CMake 專案可以搭配 CPack 來進行打包。

CPack 使用上也很簡單,先安裝 CPack

sudo apt-get install cpack

然後修改專案裡的 CMakeLists.txt ,加入以下幾行

SET(CPACK_GENERATOR "DEB")
SET(CPACK_PACKAGE_VERSION_MAJOR "1")
SET(CPACK_PACKAGE_VERSION_MINOR "2")
SET(CPACK_PACKAGE_VERSION_PATCH "0")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Yan-ren Tsai")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libavahi-compat-libdnssd1,libplist3,libssl1.1,libgstreamer1.0-0,libgstreamer-plugins-base1.0-0,gstreamer1.0-libav,gstreamer1.0-vaapi,gstreamer1.0-plugins-bad")
INCLUDE(CPack)

接著重新做一次前面 cmake 的步驟,最後再執行 cpack 即可

# 假設已經在 RPiPlay 目錄下
mkdir build
cd build
cmake ..
make
cpack

執行完,就會在目錄下看到 rpiplay-1.2.0-Linux.deb

使用 sudo dpkg -i rpiplay-1.2.0-Linux.deb 就可以安裝了。

參考資料

vagrant virtualbox provider 加載磁碟

前兩天想練習 LVM,所以試著在既有的 RHEL VM 裡加磁碟,但是事情沒有想的那麼簡單。原本以為就是照 Vagrant Disk Usage 文件的說明,在 Vagrantfile 裡加入

config.vm.disk :disk, size: "100GB"

就可以,但這樣不行,vagrant reload 以後,並沒有磁碟出現。

上網找解決方法,找到這篇:Add a second disk to system using vagrant

才知道是要用 provider 的 customize() 去建立磁碟並加載才行 (參考資料:Add a second disk to system using vagrant):

    tower.vm.provider "virtualbox" do |v|
      file_to_disk1 = "mydisk1.vmdk"
      unless File.exist?(file_to_disk1)
        v.customize [
           "createmedium", "disk", "--filename", file_to_disk1, "--format", "vmdk", "--size", 1024 * 1
         ]
      end
      file_to_disk2 = "mydisk2.vmdk"
      unless File.exist?(file_to_disk2)
        v.customize [
           "createmedium", "disk", "--filename", file_to_disk2, "--format", "vmdk", "--size", 1024 * 1
         ]
      end
      v.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk1]
      v.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', file_to_disk2]
    end

在建立前,先使用 File.exists? 去做檢查磁碟映像檔是否存在,不存在,就呼叫 createmedium 來建立。接著再用 storageattach 加載到 VM 上就可以了。

如果有錯誤訊息,說沒有 SATA Controller,請開啟 VirtualBox 去看該 VM 是不是有 SATA Controller。

參考資料:

  1. vagrant – Set storage size on creation of VM VirtualBox – Unix & Linux Stack Exchange
  2. Vagrant Tricks: Add extra disk to box – real world IT
  3. https://gist.github.com/leifg/4713995

ansible-builder

看到這篇:紅帽推出IT自動化工具Ansible Builder以加速執行環境創建 | iThome ,所以就來試試看。

就我試用過以後,我的理解是,這工具可以幫忙創建出一個具有 Ansible 環境的 docker image。

環境是定義在 execution-environment.yml 裡,讓我們直接看範例

---
version: 1

# 即基礎 image,目前來說,都是用 quay.io/ansible/ansible-runner:stable-2.9-devel
base_image: 'quay.io/ansible/ansible-runner:stable-2.9-devel'

# 需要自訂 ansible.cfg 的話,這邊就是填 ansible.cfg 的路徑檔名
ansible_config: 'ansible.cfg'

# 相依
# galaxy 是填 requirements.yml,檔案裡描述 playbook 會用到的 role/collection,沒用到可以不填
# python 則是填 requirements.txt,檔案裡描述會使用到的 Python modules,沒用到可以不填
dependencies:
  galaxy: requirements.yml
  python:

# 額外要加入的 docker image 建置步驟
# prepend 會在預定的建置步驟之前
# append 則是在預定的建置步驟之後
additional_build_steps:
  prepend: |
    RUN whoami
    RUN cat /etc/os-release
  append:
    - RUN echo This is a post-install command!
    - RUN ls -la /etc

有了 execution-environment.yml 之後,就可以用 ansible-builder 來建置。

首先,得先安裝:

# python3
pip3 install ansible-builder

接著就可以建置了

ansible-builder build --tag=example

建置完成,會有 docker image,在目錄下則會出現 context 資料夾,這個資料夾裏面就是 ansible-builder 建置過程中所產出的 Dockerfile 以及建置 Docker image 所需的檔案。

打開 Dockerfile ,就會看到 ansible-builder 幫我們產出了什麼。

FROM quay.io/ansible/ansible-runner:stable-2.9-devel as galaxy

ADD ansible.cfg ~/.ansible.cfg

ADD requirements.yml /build/

RUN ansible-galaxy role install -r /build/requirements.yml --roles-path /usr/share/ansible/roles
RUN ansible-galaxy collection install -r /build/requirements.yml --collections-path /usr/share/ansible/collections

RUN mkdir -p /usr/share/ansible/roles /usr/share/ansible/collections

FROM quay.io/ansible/python-builder:latest as builder

ADD requirements_combined.txt /tmp/src/requirements.txt
RUN assemble

FROM quay.io/ansible/ansible-runner:stable-2.9-devel

RUN whoami
RUN cat /etc/os-release

COPY --from=galaxy /usr/share/ansible/roles /usr/share/ansible/roles
COPY --from=galaxy /usr/share/ansible/collections /usr/share/ansible/collections

COPY --from=builder /output/ /output/
RUN /output/install-from-bindep && rm -rf /output/wheels
RUN echo This is a post-install command!
RUN ls -la /etc

大抵來說,

  1. 使用了 multi stage build 以減少 docker image 的大小
  2. 使用 ansible-galaxy 安裝相依的 role/collection
  3. 會看到 additional_build_steps 裡描述的步驟

好,那建置出 docker image 以後,怎麼使用呢?

假設 playbook 是放在 project 目錄下,那麼就這樣執行

docker run --rm -v /runner/project:$(pwd)/project -it example:latest ansible-playbook -i localhost, -c local /runner/project/test.yml

這邊稍微取了點巧,只簡單用 local connection (-i localhost, -c local) 在本機執行,你也可以在這邊使用自己的 inventory。

建置出 Ansible 執行環境的 docker image 以後,除了可以固定住執行 Ansible playbook 的環境,也有利於打造出標準化的 CD 環境,進而減少開發與佈署的時間。

直接用 SSH 登入 vagrant 虛擬機失敗

試著直接使用 SSH 登入 vagrant 開出來的 Ubuntu 虛擬機,會出現錯誤訊息:

SSH Login Failed : Permission denied (publickey,gssapi-keyex,gssapi-with-mic)

可是用 vagrant ssh 卻可以登入,用 vagrant ssh 登入進去查,SSH daemon 有啟動,所以 SSH 服務是沒問題的。後來透過錯誤訊息才查到,是 SSH Daemon 裡的 PasswordAuthentication 被設定為 no 了。所以修改 /etc/ssh/sshd_config ,將 PasswordAuthentication 設定為 yes 後,就可以用 ssh 登入了。

vagrant ssh 之所以可以登入,是因為在初始化虛擬機時,預先產生好 SSH Key,並且把 SSH public key 放到虛擬機裡了。另外一種解決方法,就是使用產生好的 SSH private key 來登入。

ssh -i .vagrant/machines/<your_machine_name>/virtualbox/private_key ubuntu@<your_machine_ip>

參考資料: