分類
記事

2024哈薩克之行01

2024-05-10 晴

由於沒有任何一路公交車可以到達霍爾果斯口岸,所以早上從酒店打網約車到達霍爾果斯(Khorgas)國際客運站,司機是一位姓馬的維吾爾女性,車開得很好。她不喜歡 OPPO 手機裡 QQ 音樂放出來的歌曲(流行和迪曲),切了好幾次歌。車內很乾淨,未見攝像頭。

到客運站後先到售票處購買前往雅爾肯特(Zharkent)的車票,90 元一位。買票的時候只查驗了身份證沒有看護照。然後拿著車票和身份證到旁邊窗口,裡面的工作人員會給車票蓋一個邊檢的章。之後就可以返回後車大廳通過安檢等車了。在我們蓋章前有三個人插隊,但是表示只是詢問一下。他們把票和身份證給到窗口,工作人員對著電腦敲了鍵盤,等了一小會兒搖了搖頭把身份證和票給回他們,說還沒好。他們就失望地到旁邊接著等了,似乎已經等了一會兒了。進入客運站前有人拿著人民幣和堅戈來詢問是否需要兌換貨幣。進入候車廳後會有人兜售電源插頭轉換器,10 元一個。

候車大廳裡哈薩克方向有兩個乘車口,一個是到雅爾肯特另一個是到阿拉木圖。工作人員隔一會兒放一波人到大巴車上,大巴車沒有發車時間表,坐滿了就會開走。第一站非常近,所有人帶上行李下車進入中方的出境廳。在進入出境聽前會有工作人員檢查護照和車票並在車票上打孔。進入出境聽後排隊在自助機上刷護照和驗臉,然後行李過安檢,最後來到邊檢的人工窗口。邊檢詢問的仔細,所以隊伍緩慢。詢問的問題包括但不限於:去哈薩克做什麼?(旅遊、工作)在哈薩克呆多久,都去哪裡?你的職業是什麼?是否是少數民族?如果過往出入境記錄有缺失,也會詢問當時去了哪裡。我更新護照的時候填寫要去土耳其旅遊,但後來並沒有去,所以跟我確認了很多遍這次是否要去土耳其。還叫來另一位工作人員仔細看了我的護照,我也給他們看了行程表和回程機票。蓋了出境章後就再排隊上大巴,幾分鐘後達到哈方入境廳。下車前會有佩戴手銬的哈方人員上車檢查一次護照,等大廳人少後乘客才能從大巴上下來進入入境廳。邊檢查看護照、拍照、蓋章,沒有詢問問題。然後安檢行李,再次排隊上大巴。出了中方出境廳的時候和進入哈方入境廳的時候都有洗手間。由於上大巴沒有指示牌,我們差點上了一個旅遊團的大巴。後來上了大巴後還有些擔心大巴會不會是直接去阿拉木圖的。直到大巴駛出高速我們才松了一口氣。

從霍爾果斯汽車站到雅爾肯特大概花了三個小時,大巴上上下下每次都要等待,耽誤不少時間。到達亞爾肯特車站後,有很多出租車詢問是否要去阿拉木圖。車站後面有洗手間,衛生堪憂,收費 50 堅戈或 1 人民幣。出站口有小商店寫著出售 SIM 卡,附近也有幾家常見的電信營業廳。我們使用 2GIS 應用,步行到附近的 Halyk Bank 的 ATM 取了 100,000 堅戈,招商銀行短信提示取款人民幣1649.86元,招行手機應用中可以看到還有額外 10 元手續費。由於已經很餓,所以在最近的一家餐廳 Sunday 吃的午餐。服務員沒有懂英語的,於是拿手機給我們翻譯了一下菜單,我們點了一個 Sunday 拉麵和餃子、一杯摩卡咖啡和一杯檸檬紅茶。拉麵本身是方便麵,但是湯很不錯,餃子是肉餡包的圓圓的像一個個小元寶。餐廳出品和服務都很好,當時不知道哈薩克是否要給小費,而且小票上似乎已經加收 10% 的費用,所以我們就沒有另給小費。

步行到酒店,酒店前台阿姨也完全不懂英語。我們把 Agoda 預訂單給她看,但是預訂單上是英語她還是看不懂。於是我們只好指著入住日期和離店日期跟她解釋我們要住兩晚。她跟我們比一晚 10,000 堅戈,我們付了錢,她帶我們去看一樓的一個房間,那是一間雙床房。我們告訴她我們想要一間大床房,然後她給我們拿來了一次性牙刷!再次溝通清楚後她領我們到了二樓的大床房,加收了 2,000 堅戈。門口的服務員告訴我們早餐是七點到十點。房間裝修沒多久,壁紙窗簾和床品的很新,毛巾和暖氣片很舊。房間裡有一個茶几、一張桌子、兩把有靠背的椅子和兩個床頭櫃。電源插座有三個也夠用,還有一台未插電的冰箱在窗台。在牆上高高地掛著的電視是好的,機頂盒也是好的,雖然沒有遙控器但都可以通過按鍵操作。不過由於沒有連接機頂盒和電視機的信號線,所以無法看電視。似乎也沒有 WiFi,由於溝通不暢所以也沒再去問。淘寶上買的電話卡,按照指引插入後打開漫遊和 4G 後並沒有網絡。還好當時作為備用開通了移動的漫遊(1 GB 流量,30 天有效期,17.1 元,北京 IP,更高的牆,不過機場還能用),詢問淘寶客服後,客服讓把卡上的編號發給他,他在後台操作後手機就連上網了。我檢查過 APN,前後沒有改動過所以就是需要客服手工操作下,這個流程比較坑。這張流量卡是 10GB 流量,30 天有效期,87.89 元,華沙 IP。兩張卡漫遊的網絡都是Beeline KZ,移動 APN 是 cmnet,流量卡 APN 是 plus。網絡速度不錯,在 4G 和 4G+ 間切換。房間裡沒有熱水壺,不喝水可不行,所以硬著頭皮去問。然後從前台拿來了一個水垢非常厚的電熱水壺。洗了之後燒了一壺水。水還沒晾涼的時候聽到敲門聲,是另一個中國客人,來拿電水壺,說酒店只有這一個電水壺。酒店窗口曾經有紗窗,但是翻新後似乎還沒裝上新的紗窗,好在有個拖地的沙簾,可以當作紗窗阻擋飛蟲。

晚餐去吃的,拌麵和炸餃子都不錯,奶茶雖然有些淡,但是很大一壺。一共大約 4,000 堅戈。結賬的時候由於也是看到 10% 的費用,所以沒有另付小費。中午那家找零後沒有給小票,但是這家給了小票。回酒店翻譯了一下,小票最低部有兩行字大意是歡迎給服務員小費,但是給不給由您來決定。所以可能還是應該再留一些小費,下次再有機會吧。谷歌翻譯有時候很能誤導人,比如我們在點飲料的時候,奶(milk)茶被它翻譯成了摩洛哥茶。吃完飯在附近 Toimart 超市買了罐阿拉木圖啤酒(為了解渴和解饞)和一小盒 NIVEA 霜(天氣乾燥,腳踝都有花紋出現)。進超市購物前需要在自助存包櫃存包。回酒店的路上有的路段沒有路燈,可以看到新月中的黑色部分以及頭頂正上方的北斗七星。路上的狗體型毛色各異,但是都很從容。冰啤酒好喝,酒精 4.4 度,罐體上只有哈薩克語和俄語。NIVEA 鐵盒上也沒有英文,只多了一個烏茲別克語。浴室衛生一般,有一個浴缸固定在一個鐵架子上,洗澡時站在浴缸裡鐵架子搖搖晃晃的感覺不太安全。浴缸邊緣的牆上有個金屬構件,應該是裝浴簾桿的,但是沒有浴簾桿也沒有浴簾。所以洗完淋浴洗手間地面會到處都是水。馬桶蓋沒有緩衝,如果推下去的話會發出巨響,洗手池的管道底部卡了一隻牙刷。衛生紙餘量不多且富有摩擦力。鏡前的架子上有免費的一次性牙刷、牙膏(廣州產)、肥皂和洗髮水。洗髮水上有哈俄英三語寫著洗髮水以及 I ♥️ QAZAQSTAN,背面寫作 Made in P.R.C。吹風筒工作正常,床也軟硬適中。現在的溫度很舒服不用開空調,夜裡沒有噪音,睡的不錯。


附加信息:

外交部領保中心祝您健康平安!請嚴防假冒使領館名義的電信詐騙,注意槍擊、砸車盜搶等治安事件,留意災害預警,不參與賭博活動。請注意疫情防護。下載「中國領事」APP了解更多信息。哈薩克斯坦報警電話:102,緊急救助電話:103。外交部全球領事保護與服務應急熱線+86-10-12308/65612308。駐哈薩克斯坦使館領保電話+77017470186;駐阿拉木圖總領館領保電話+77272362230。中國文化和旅遊部溫馨提示,文明旅遊「三講三不」:講安全、講禮讓、講衛生;不大聲喧譁、不亂寫亂畫、不違法違規。」中國移動
您已抵達哈薩克斯坦,出境用移動,心級服務,一路隨行! 【上網】3元包3M,每天30元封頂,暢享1GB高速流量,達量限速,無需辦理即可享用 【通話】接聽電話、撥打內地及漫遊地均爲0.99元/分鐘 【短信】發內地0.39元/條,接收免費 【優惠】回復GMYDYL可訂購國漫優惠包;如需特價訂購機票、酒店等,可下載「無憂行」 【客服】更多資費及服務,請免費撥打+8613800100186 【備註】上網請確保手機數據漫遊已打開,撥打內地號碼請加撥+86,撥打漫遊地號碼請加撥+77,長按「0」撥出「+」 中國移動

當前堅戈與人民幣匯率:
100,000 KZT = 1650 CNY
10,000 KZT = 165 CNY
5,000 KZT = 82.5 CNY
1,000 KZT = 16.5 CNY

分類
程序

使用 Python 或/和 Cloudflare Worker 代理 NextDNS 的 DoH 服務

Previously:使用 nginx 代理 NextDNS 的 DoH 服務

使用 Cloudflare Worker 代理 NextDNS 的 DoH 服務

使用 tina-hello 的 doh-cf-workers 項目可以方便的建立一個 DoH 代理。由於只需要一個 index.js 文件,所以我這裡轉載一下。默認的示例是 Cloudflare 的 DoH,切換成 NextDNS 的話只需要修改 doh 和 dohjson 的網址,其他都不用動。

// SPDX-License-Identifier: 0BSD

const doh = 'https://dns.nextdns.io/YOUR_ID/YOUR_TAG'
const dohjson = 'https://dns.nextdns.io/YOUR_ID/YOUR_TAG'
const contype = 'application/dns-message'
const jstontype = 'application/dns-json'
const r404 = new Response(null, {status: 404});

// developers.cloudflare.com/workers/runtime-apis/fetch-event/#syntax-module-worker
export default {
    async fetch(r, env, ctx) {
        return handleRequest(r);
    },
};

async function handleRequest(request) {
    // when res is a Promise<Response>, it reduces billed wall-time
    // blog.cloudflare.com/workers-optimization-reduces-your-bill
    let res = r404;
    const { method, headers, url } = request
    const searchParams = new URL(url).searchParams
    if (method == 'GET' && searchParams.has('dns')) {
        res = fetch(doh + '?dns=' + searchParams.get('dns'), {
            method: 'GET',
            headers: {
                'Accept': contype,
            }
        });
    } else if (method === 'POST' && headers.get('content-type') === contype) {
        // streaming out the request body is optimal than awaiting on it
        const rostream = request.body;
        res = fetch(doh, {
            method: 'POST',
            headers: {
                'Accept': contype,
                'Content-Type': contype,
            },
            body: rostream,
        });
    } else if (method === 'GET' && headers.get('Accept') === jstontype) {
        const search = new URL(url).search
         res = fetch(dohjson + search, {
            method: 'GET',
            headers: {
                'Accept': jstontype,
            }
        });
    }
    return res;
}
#測試下 GET 請求
curl -H 'accept: application/dns-json' 'https://YOURPROJECT.YOURWORKER.workers.dev/dns-query?name=ft.shaman.eu.org&type=A'
#POST請求由於需要構造 DNS 參數,所以就不測了

使用 Python 代理 NextDNS 的 DoH 服務

輕量級的 API 框架我不熟悉,所以這裡還是用 Django。

#file:app1/views.py
from django.http import HttpResponse
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import requests

@csrf_exempt
def forward_to_doh(request):
    cloudflare_doh_url = "https://YOURPROJECT.YOURWORKER.workers.dev/"
    contype = 'application/dns-message'
    jstontype = 'application/dns-json'

    try:
        if request.method == 'GET':
            if 'dns' in request.GET:
                params = {'dns': request.GET['dns']}
                headers = {'Accept': contype}
                response = requests.get(cloudflare_doh_url, params=params, headers=headers)
                return JsonResponse(response.json(), status=response.status_code)
            elif request.headers.get('Accept') == jstontype:
                response = requests.get(cloudflare_doh_url + '?' + request.GET.urlencode(), headers={'Accept': jstontype})
                return JsonResponse(response.json(), status=response.status_code)
        elif request.method == 'POST':
            if request.headers.get('content-type') == contype:
                headers = {'Accept': contype, 'Content-Type': contype}
                data = request.body
                response = requests.post(cloudflare_doh_url, data=data, headers=headers)
                return HttpResponse(response.content, content_type=response.headers['Content-Type'], status=response.status_code)
        else:
            return JsonResponse({'error': 'Unsupported request method'}, status=405)
        return JsonResponse({'error': 'Not Found'}, status=404)

    except requests.exceptions.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)
#file:mysite/urls.py
from django.urls import include,path
from app1 import views

urlpatterns = [
    path('YourSecNextDns/', views.forward_to_doh, name='forward_to_doh'),
    path('i/', include('i.urls')),
]
#測試下 GET 請求
curl -H 'accept: application/dns-json' 'https://YOUR_DOMAIN.LTD/YourSecNextDns/?name=ft.shaman.eu.org&type=A'

上面的請求經過三次請求,速度(高達秒級)自然是比不了直連。但是為了體驗 DoH,還是可以用用看。反正網速本身也不快,DNS 慢一點完全可以怪到網速上。

分類
软件

觀鳥輔助工具 whoBIRD

whoBIRD可以在手機離線的情況下,根據當前地理位置和所處時間通過 BirdNET 訓練的模型識別鳥叫。有時候用眼睛找鳥是很困難的,但是有 whoBIRD 的幫助,會更容易分辨是自己已知的鳥類還是一個叫聲很相似,但是是不同的鳥類。對於新到一個地方有很多未知鳥類時也很有幫助。如果當時手機有網絡,還能直接顯示出鳥的照片。當然也可以等手機有網絡後從歷史記錄里慢慢查看之前聽到了什麼鳥叫。

分類
Linux 软件

使用 nginx 代理 NextDNS 的 DoH 服務

免費版的 NextDNS 每個月有 300,000 次請求,個人一般是夠用的。通過 nginx 代理其 DoH 服務可以用自己的域名來使用 NextDNS 的服務。Nginx 配置文件 /etc/nginx/conf.d/MY.DOMAIN.conf 如下:

# Cache the dns query
proxy_cache_path /var/cache/nginx/dns levels=1:2 keys_zone=dns_cache:10m max_size=1g inactive=1d use_temp_path=off;

server {
    server_name my.domain;

    root /usr/share/nginx/html;

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/my.domain/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/my.domain/privkey.pem; # managed <p>by</p> Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    http2 on;
    resolver 45.90.28.136;

    location /YOUR_DNS_QUERY_PATH {
        proxy_pass https://dns.nextdns.io/YOUR_ID/YOUR_TAG;
        proxy_set_header Host dns.nextdns.io;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache dns_cache;
        proxy_cache_valid 1d;
        proxy_cache_use_stale error timeout updating;
    }
    
    location / {
    }
}
server {
    if ($host = my.domain) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    listen [::]:80;
    server_name my.domain;
    return 404; # managed by Certbot


}

Nginx 搭配 Cerbot 獲取免費證書請參考:網站用上了letsencrypt的免費ssl證書

搭建完成後可以通過 curl 來檢查服務是否正常:curl -H 'accept: application/dns-json' 'https://my.domain/YOUR_DNS_QUERY_PATH?name=ft.shaman.eu.org&type=A'

使用 personalDNSfilter 以在安卓手機上使用 DoH

使用 personalDNSfilter (去 F-droid 下載)實現的本地 VPN 來修改系統的DNS查詢,它同時還能攔截廣告。配置非常簡單,只需要在 DNS 配置欄選中禁用 DNS 服務器查找,選中文本編輯模式,並在輸入框中加入下面一行並啟用即可。

[MY.SERVER.IP]::443::DOH::https://my.domain/YOUR_DNS_QUERY_PATH

也可是使用重一點的 Rethink 來管理 DNS。加入自己的 DoH 也很簡單。選擇 Other DNS,DoH,新增。名稱隨便,Resolver URL 填:https://my.domain/YOUR_DNS_QUERY_PATH 即可。

在 Xfce 口味的 Fedora 上使用 DoH

似乎是沒辦法直接在圖形界面上進行設置。我最終是用熟悉的 dnscrypt-proxy 2 來代理。不熟悉的朋友請參考:Fedora 使用 DNSCrypt。只需要修改三處文件即可:

#file:dnscrypt-proxy.toml

#設置 server_names,默認是注釋掉的
server_names = ['mydns']

#如果在中國,可以把 bootstrap_resolvers 設置成 114
bootstrap_resolvers  = ['114.114.114.114:53', '8.8.8.8:53']

#拉到文件底部,添加這兩行
  [static.mydns]
  stamp = 'sdns://AgAAAAAAAAAABzEuMS4xLjEACW15LmRvbWFpbhQvWU9VUl9ETlNfUVVFUllfUEFUSA'

stamp 的生成請打開這個網頁:Online DNS Stamp calculator Protocol 選擇 DoH,IP 寫 IP,Host 寫域名,Path 寫/YOUR_DNS_QUERY_PATH ,然後複製生成的 Stamp 就可以了。

今天是 2024 年 4 月 1 日,看看自己域名的 DoH 可以存活多久。安卓網絡設置里雖然可以直接指定 DoT,NextDNS 的 DoT 也可以用 Nginx 代理,但是感覺陣亡幾率更大(專用端口),所以我選擇了更穩妥一點的 DoH。

2024-04-05: 移動網絡偶爾出現 SSL handshake timed out IO Error occured! Check network or DNS config! 和 Read timed out IO Error occured! Check network or DNS config! 但是還是能用。

2024-04-06: 晚上移動網絡開始出現 SSL handshake aborted: ssl=0x7b2db05fc8: I/O error during system call, Connection reset by peer IO Error occured! Check network or DNS config! 基本用不了了。之間訪問網站也顯示 The connection was reset 。所以清明節沒過完域名就掛了,存活時間約 5 天。如果想要繼續使用被屏蔽的域名,或者直接使用 NextDNS,無論是 DNSCrypt 還是 personalDNSfilter 都支持代理。一息尚存的 DNSCrypt 內置不少 DNS,還可以在不用代理的情況下使用。

2024-04-15:偶爾外出就餐時連接餐廳的 WiFi,發現電信的寬帶仍然可以使用。但是移動網絡和移動寬帶已經完全無法連上。


另請參閱:使用 Python 或/和 Cloudflare Worker 代理 NextDNS 的 DoH 服務

本文更新於 2024/04/24。

分類
Linux

Fedora 39 Xfce tricks

前段時間用了一些 KDE 團隊開發的應用,又聽說 Linux 界的安卓模擬器新星 Waydroid 很厲害,於是裝個 KDE Plasma 體驗。結果離開了 X 才只知道 X 的好!KDE Plasma 在默認配置下,瀏覽器播放視頻會有輕微卡頓,如果快進快退則卡頓感更加明顯。而且原來可以輕鬆設定的全局熱建,搜索一通居然發現無法實現!在英文系統里裝中文輸入法,也是個痛。所以用了一天時間就跟這酷炫的桌面拜拜了——裝回了順手的 Xfce。

多媒體工作站

	
sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm

sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
sudo sh -c 'echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/vscode.repo'

dnf check-update
sudo dnf install code vlc ffmpeg libreoffice calibre

安裝拼音輸入法

Applications > Settings > Input Method Selector,選擇 Use IBus。然後點擊旁邊的 Preferences 打開 IBus 的設置。

在 General 標籤頁可以將候選詞設置為橫排(默認為豎排)。在 Input Method 標籤頁點擊 Add 按鈕添加輸入法(選擇 Chinese > Intelligent Pinyin)。添加後選中拼音輸入法,在點擊右邊的 Preferences 可以設定拼音輸入法,比如候選詞數量、候選詞翻頁按鍵、字典詞庫以及中英文切換鍵等。設置過程中如果有問題,可能是需要登出一下才會生效。

調大字體

歲月不饒人,雖然屏幕是 1920*1080 全高清,但是字體顯示真的有點小,看久了會累。在 Applications > Settings > Apperance 中的 Fonts 標籤頁可以設置 DPI,改為 119,字體大小就舒服多了。Style 標籤也有很多主題,但是丑的居多,個人覺得默認的 Adwaita 確實已經是最好看的了。在 Applications > Settings > Window Manager 中也可以設定窗口樣式,推薦大家試試 Mint-Y-Aqua。

睡眠模式掉電快

在我的電腦上,默認的睡眠模式是 s2idle,如果想要在睡眠時省電,需要改成 deep 模式。

#查看當前模式
cat /sys/power/mem_sleep
#可能會輸出 [s2idle] 或[s2idle] deep
#通過下面命令設定成 deep 模式
echo deep | sudo tee /sys/power/mem_sleep
#再次查看 /sys/power/mem_sleep
#應該變成 s2idle [deep]
#此時可以嘗試睡眠觀察一下電量消耗
#如果沒有問題,還需要通過下面命令將這個模式保存下來

#打開 /etc/default/grub 文件
sudo nano /etc/default/grub
#找到 GRUB_CMDLINE_LINUX= 開頭的一行
#有的系統是 GRUB_CMDLINE_LINUX_DEFAULT= 但是沒關係
#這行中一般都還有一個關鍵字 quiet
#在這行的末尾,引號前加入
 mem_sleep_default=deep
#然後保存文件
#最後執行下更新啟動項
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Virtual Box

使用sudo dnf install VirtualBox virtualbox-guest-additions即可安裝 VirtualBox,現在最新版是 7.0 。安裝後進入虛擬機發現共享文件以及顯示縮放都不能用。原來是自動下載失敗了,需要手動下載虛擬機增強插件 ISO。從 https://download.virtualbox.org/virtualbox/7.0.14/VBoxGuestAdditions_7.0.14.iso 下載後,掛載上就可以在虛擬機里安裝增強插件了。


其他小撇步另請參考:Fedora Workstation Tricks

本文更新於 2024/03/16。

分類
Linux 软件

Turmux X11 以及 VSCode

本篇文件介紹如何在安卓手機上運行 VSCode 來實現在旅途中繼續編碼。我使用的手機是 2018 年的 Xperia XZ2,內存只有 4GB,CPU 型號是 Qualcomm SDM845,屏幕是 5.7 in (140 mm) 1080p (2160 × 1080) IPS LCD, ~424 pixel density。最終效果如下:

VSCode On Debian With Termux

藉助 Termux 我們得以在安卓上運行多種 Linux,之所以選擇 Debian 是因爲它相對輕量且不含 systemd (安卓不支持)。本文得以形成主要是參考了 Termux X11:手機的X伺服器使用教學Android手機安裝Linux發行版:Termux proot-distro使用教學 以及 VSCode installation tutorial with Termux-x11,在此一併感謝!

如果你的手機性能良好,推薦按照 Ivon 的文章安裝 Xfce4 桌面環境,這樣東西就一應俱全了(除了不能運行 Docker,安卓內核不支持)。

安裝 Termux

雖然可以直接去 Github 下載安裝包,但是還是建議去 F-Droid 安裝Termux。當前的最新版本是 0.118.0。安裝完成後執行下列命令:

pkg update
pkg upgrade
pkg install nano proot-distro x11-repo termux-x11-nightly
termux-setup-storage

安裝 X11

這裏需要到 Github 下載 X11 的安裝包。如果沒有 Github 賬戶,可以從這裏下載我安裝的這個版本。

安裝 Debian

手機性能好的話,可以嘗試其他口味的 Linux 以及桌面環境。我的手機連 Xfce4 也運行不起來(X11 裏可以,但是 Debian 裏就會自動退出),所以我使用輕量的 openbox。

proot-distro install debian
#進入 Debian
proot-distro login debian
apt update
apt upgrade
apt install nano sudo wget git
#添加普通用戶
passwd
groupadd storage
groupadd wheel
groupadd video
#替換 [USER] 爲你想要的名字
useradd -m -g users -G wheel,audio,video,storage -s /bin/bash [USER]
passwd [USER]
visudo
#在 root ALL=(ALL:ALL) ALL 這行的後面添加
[USER] root ALL=(ALL:ALL) ALL
#保存後使用 exit 退出 Debian

創建兩個腳本來啓動和關閉 X11:

##以下是startDebian.sh
#!/bin/bash
export DISPLAY=:0
killall -9 termux-x11 termux-wake-lock
# 啟動Termux X11
am start --user 0 -n com.termux.x11/com.termux.x11.MainActivity
XDG_RUNTIME_DIR=${TMPDIR}
termux-x11 :0 &
sleep 3

proot-distro login debian --user [USER] --shared-tmp
##以下是stopDebian.sh
#!/bin/bash
killall -9 termux-x11

然後給予可執行權限:

chmod +x startDebian.sh
chmod +x stopDebian.sh
#然後執行 startDebian.sh 就能就如 Debian 了
./startDebian.sh
#若出現報錯 ERROR: openbox-xdg-autostart requires PyXDG to be installed 可以按回車鍵忽略
#安裝窗口管理器
sudo apt install xorg openbox
sudo apt install firefox-esr fonts-noto-cjk proxychains4 curl tint2 xclip pcmanfm
#火狐:你需要一個瀏覽器
#fonts-noto-cjk:字體
#proxychains4:沒有代理不科學
#curl:安裝 curl 可以修復使用 proxychains4 時 library "libdl.so.2" not found 的錯誤
#tint2:任務欄讓桌面更美好
#pcmanfm:桌面環境怎能少得了文件管理器
#xclip:把剪切版的內容從安卓傳遞到 Debian

# .bashrc 中添加下面文本

alias pp='termux-clipboard-get | xclip -sel clipboard'
alias p='proxychains4'

export DISPLAY=:0
if ! pgrep -x "openbox" > /dev/null; then
    openbox-session &
    tint2 &
fi

安裝 VSCode

前往 VSCode 下載頁,下載 Arm64 版本的 .deb 安裝包。可以通過瀏覽器下載,然後下載頁會有下載的直鏈,複製後用 wget 下載就好。

#安裝 VSCode
sudo dpkg -i /sdcard/Downloads/code-[VERSION].deb
#如果出現報錯嘗試
sudo apt --fix-broken install
#然後再試試上面的 dpkg 安裝指令

最在啓動欄創建兩個常用的快捷啓動方式:先修改下桌面快捷方式

#把 /usr/share/applications/code.desktop 中的
Exec=/usr/share/code/code --unity-launch %F
#改爲
Exec=/usr/share/code/code --no-sandbox %F

#把 /usr/share/applications/firefox-esr.desktop 中的
Exec=/usr/lib/firefox-esr/firefox-esr %u
#改爲
Exec=/usr/lib/firefox-esr/firefox-esr --no-sandbox %u

兩個手機點一下桌面(黑屏)呼出右鍵菜單,選擇 Applications > Settings > Tint2 Settings 。點擊左上角編輯,Panel 推薦設置在左邊,length 150%,size 60 pixels。Panel items 留下 Launcher 和 Taskbar 即可。Lanucher 裏選擇 VS Code 和 Firefox ESR 保存即可。

既然提到了命令行啓動火狐,順便記錄下火狐的多用戶。在命令行加上 -P 可以啓動 Profile 管理器。在管理器裏可以新增、重命名以及設置默認的用戶。想以用戶 42 啓動,則把上面快捷方式裏的運行項改爲 /usr/lib/firefox-esr/firefox-esr --no-sandbox -P 42 %u 即可。

Firefox 在 A Profile 升級後,从 B Profile 啟動可能會出現問題:"You've launched an older version of firefox" "Using an old version of Firefox..."。此時可以在啟動命令後加上 -allow-downgrade 就可以啟動了。然後關閉火狐就可以正常啟動了。

使用場景

開始使用

  1. 啓動 Termux
  2. ./startDebian.sh

退出

  1. 切換到 Termux,執行 exit
  2. ./stopDebian.sh

其他小撇步

字體非常小:在 Debian 家目錄新增文件 nano ~/.Xdefaults 內容爲 Xft.dpi: 192 即指定 dpi 分辨率爲 192。如果個別應用字體還是很小,可以嘗試通過應用自己的配置來調整顯示大小。顏色深度也可以在這裏配置,例如:Xft.depth: 16

剪切版:從 Debian 到安卓默認是沒問題的,除非你在 X11 的配置項裏禁用了。但是從安卓到 Debian 卻不輕鬆。目前一個可行的方案就是上面使用 xclip 的方式:首先切換到 Termux,運行 alias pp,然後就可以在 Debian 裏粘貼了。

中文輸入:本篇沒有安裝中文輸入法,以節省更多資源予 VSCode。

掛載外部 SD Card 到 Debian:啓動時加入 --bind /data/data/com.termux/files/home/storage/external-1:/sdcard1 就會將外部儲存卡的可用目錄掛載到 proot 系統裏的 /sdcard1。手機裏的內部儲存默認是掛載在 /sdcard 的。

本文更新於 2024/03/03。

分類
Linux

使用 xinput 映射鼠標按鍵

鼠標左鍵故障無法使用了,可以使用 xinput 將其他不常用的按鍵映射爲左鍵。Fedora 的 Xfce 桌面環境沒有默認安裝 xinput,需要手動安裝一下。

sudo dnf install xinput
#查看設備列表
xinput list
#比如我的鼠標會找到
Bluetooth Mouse M336/M337/M535 Mouse    	id=20	[slave  pointer  (2)]
#後續操作使用 20 和 Bluetooth Mouse M336/M337/M535 Mouse 都可以
#查看此鼠標當前的按鍵映射配置
xinput --get-button-map 'Bluetooth Mouse M336/M337/M535 Mouse'
1 2 3 4 5 6 7 8 9 10 11 12
#查看當前鼠標按鍵
xinput test 'Bluetooth Mouse M336/M337/M535 Mouse'
#當你操作鼠標時機會顯示哪個按鍵有動作
#通過映射拯救左鍵
xinput set-button-map 'Bluetooth Mouse M336/M337/M535 Mouse' 1 1 3 4 5 1 1 1 1 1 1 1
#我把不常用的鍵都指定成左鍵了
#測試沒有問題後可以將映射的指令添加到開機啓動裏
#Applications > Settings > Session and Startup > Application Autostart
/usr/bin/xinput set-button-map 'Bluetooth Mouse M336/M337/M535 Mouse' 1 1 3 4 5 1 1 1 1 1 1 1

用了一小段時間後發現,似乎鼠標滾輪也不是很好,所以最終在屋裏找到另一隻鼠標後,放棄了這隻。建議大家旅行時攜帶鼠標最好有個盒子,免得擠壓導致鼠標死亡。