MoreRSS

site iconFrytea | 宋天伦修改

专注于云计算和AI相关技术,喜欢摄影、阅读、观影、写作,安静的做事情。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Frytea | 宋天伦的 RSS 预览

ceph mon Operation not permitted 问题解决

2026-04-03 11:25:31

自己构建的 ceph 发现 mon 起不来,报错如下:

Apr 03 11:14:30 debian systemd[1]: Started Ceph cluster monitor daemon.
░░ Subject: A start job for unit [email protected] has finished successfully
░░ Defined-By: systemd
░░ Support: https://www.debian.org/support
░░ 
░░ A start job for unit [email protected] has finished successfully.
░░ 
░░ The job identifier is 6997.
Apr 03 11:14:31 debian ceph-mon[374601]: 2026-04-03T11:14:31.084+0800 ffffaf907040 -1 load: jerasure load: lrc load dlopen(/usr/lib/ceph/erasure-code/libec_isa.so): /usr/lib/ceph/erasure-code/libec_isa.so: cannot make segment writable for relocation: Operation not permitted
Apr 03 11:14:31 debian systemd[1]: [email protected]: Main process exited, code=exited, status=1/FAILURE
░░ Subject: Unit process exited
░░ Defined-By: systemd
░░ Support: https://www.debian.org/support
░░ 
░░ An ExecStart= process belonging to unit [email protected] has exited.
░░ 
░░ The process' exit code is 'exited' and its exit status is 1.
Apr 03 11:14:31 debian systemd[1]: [email protected]: Failed with result 'exit-code'.
░░ Subject: Unit failed
░░ Defined-By: systemd
░░ Support: https://www.debian.org/support
░░ 
░░ The unit [email protected] has entered the 'failed' state with result 'exit-code'.

临时解决方案

根据 claude-sonnet 4.6 的说法:

现在最快能让服务跑起来的办法就是 systemd override,直接关掉那个内存保护:

bashmkdir -p /etc/systemd/system/[email protected]/

cat > /etc/systemd/system/[email protected]/override.conf << 'EOF'
[Service]
MemoryDenyWriteExecute=false
EOF

systemctl daemon-reload
systemctl restart ceph-mon@$(hostname)
systemctl status ceph-mon@$(hostname)

同样的问题也会出现在 ceph-osd 和 ceph-mds,可以一并处理。

for svc in ceph-mon ceph-osd ceph-mds; do
  mkdir -p /etc/systemd/system/${svc}@.service.d/
  cat > /etc/systemd/system/${svc}@.service.d/override.conf << 'EOF'
[Service]
MemoryDenyWriteExecute=false
EOF
done

systemctl daemon-reload
systemctl restart ceph-mon@$(hostname)

这个方法不需要重新编译,直接解决 Operation not permitted 的问题。

MemoryDenyWriteExecute=false 只是关闭了一个进程级别的内存安全加固选项,它的作用是:阻止进程将同一块内存页同时标记为"可写"和"可执行"。
唯一的代价是理论上轻微降低了安全加固等级,即如果 ceph-mon 进程被攻击者利用漏洞控制,攻击者稍微容易一点点注入可执行代码。对于内网存储集群这个风险几乎可以忽略。

这个办法可以临时解决,但不确定是否有风险,需要充分验证后再使用。

彻底解决方案

下面给出了一个彻底解决方案:

唯一正确的根本解法:编译时禁用 ISA 插件
debian/rules 里找到 cmake 参数,加入 -DWITH_EC_ISA_PLUGIN=OFF

bashgrep -n "cmake\|CMAKE" ~/build-ceph/ceph/ceph-16.2.7/debian/rules | head -20

找到 cmake 调用的那行,加入该参数后重新编译。

永久解决方案暂未验证。

Ascend 310P + openFuyao + NPU-Operator 故障排查

2026-04-01 22:26:36

[TOC]

故障 pod describe

[root@master1 ~]# kubectl -n kube-system describe pod ascend-device-plugin-ll46f 
Name:                 ascend-device-plugin-ll46f
Namespace:            kube-system
Priority:             2000001000
Priority Class Name:  system-node-critical
Service Account:      ascend-device-plugin-sa
Node:                 master1/10.17.30.131
Start Time:           Mon, 30 Mar 2026 11:08:32 +0800
Labels:               app.kubernetes.io/managed-by=npu-operator
                      controller-revision-hash=7df5dcb887
                      helm.sh/chart=npu-operator-0.15.0
                      name=ascend-device-plugin-ds
                      pod-template-generation=1
Annotations:          cni.projectcalico.org/containerID: c1f2adcaeaaf2bdcf0a6e09730f68231a293074e31d58f61997f714dfb520878
                      cni.projectcalico.org/podIP: 192.168.137.118/32
                      cni.projectcalico.org/podIPs: 192.168.137.118/32
                      scheduler.alpha.kubernetes.io/critical-pod: 
                      seccomp.security.alpha.kubernetes.io/pod: runtime/default
Status:               Running
IP:                   192.168.137.118
IPs:
  IP:           192.168.137.118
Controlled By:  DaemonSet/ascend-device-plugin
Init Containers:
  init-permission:
    Container ID:  containerd://4406968a522bea48dfefebae81ec53644312762af4781c25de689952ed6c2d27
    Image:         cr.openfuyao.cn/openfuyao/busybox:1.36.1
    Image ID:      cr.openfuyao.cn/openfuyao/busybox@sha256:4b8407fadd8100c61b097d63efe992b2c033e7d371c9117f7a9462fe87e31176
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      chown 9000:9000 /var/log/mindx-dl /var/log/mindx-dl/devicePlugin
      chmod 750 /var/log/mindx-dl/devicePlugin
      
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Mon, 30 Mar 2026 15:28:32 +0800
      Finished:     Mon, 30 Mar 2026 15:28:32 +0800
    Ready:          True
    Restart Count:  1
    Environment:    <none>
    Mounts:
      /var/log/mindx-dl/devicePlugin from log-path (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-gfldg (ro)
Containers:
  device-plugin-01:
    Container ID:  containerd://fcc0c4742285847e2621a9a9217502307fc7e28644fbf86b32f9c11d67a2c0ab
    Image:         cr.openfuyao.cn/openfuyao/ascend-image/ascend-k8sdeviceplugin:v6.0.0
    Image ID:      cr.openfuyao.cn/openfuyao/ascend-image/ascend-k8sdeviceplugin@sha256:a5b9612b21bcd35384f9f19a05b2d7915b865e7b2be6a30bfd7806a9b8a86f58
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/bash
      -c
      --
    Args:
      device-plugin  -useAscendDocker=true -volcanoType=false -logFile=/var/log/mindx-dl/devicePlugin/devicePlugin.log -logLevel=0
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 31 Mar 2026 10:28:58 +0800
      Finished:     Tue, 31 Mar 2026 10:28:58 +0800
    Ready:          False
    Restart Count:  274
    Limits:
      cpu:     500m
      memory:  500Mi
    Requests:
      cpu:     500m
      memory:  500Mi
    Environment:
      NODE_NAME:   (v1:spec.nodeName)
    Mounts:
      /tmp from tmp (rw)
      /usr/local/Ascend/driver from hiai-driver (ro)
      /var/lib/kubelet/device-plugins from device-plugin (rw)
      /var/lib/kubelet/pod-resources from pod-resource (rw)
      /var/log/mindx-dl/devicePlugin from log-path (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-gfldg (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True 
  Initialized                 True 
  Ready                       False 
  ContainersReady             False 
  PodScheduled                True 
Volumes:
  device-plugin:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/kubelet/device-plugins
    HostPathType:  
  pod-resource:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/kubelet/pod-resources
    HostPathType:  
  hiai-driver:
    Type:          HostPath (bare host directory volume)
    Path:          /usr/local/Ascend/driver
    HostPathType:  
  log-path:
    Type:          HostPath (bare host directory volume)
    Path:          /var/log/mindx-dl/devicePlugin
    HostPathType:  DirectoryOrCreate
  tmp:
    Type:          HostPath (bare host directory volume)
    Path:          /tmp
    HostPathType:  
  kube-api-access-gfldg:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    Optional:                false
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              openfuyao.com/npu.present=
Tolerations:                 CriticalAddonsOnly op=Exists
                             device-plugin=v2:NoSchedule
                             huawei.com/Ascend910:NoSchedule op=Exists
                             node-role.kubernetes.io/control-plane:NoSchedule
                             node-role.kubernetes.io/master:NoSchedule
                             node.kubernetes.io/disk-pressure:NoSchedule op=Exists
                             node.kubernetes.io/memory-pressure:NoSchedule op=Exists
                             node.kubernetes.io/not-ready:NoExecute op=Exists
                             node.kubernetes.io/pid-pressure:NoSchedule op=Exists
                             node.kubernetes.io/unreachable:NoExecute op=Exists
                             node.kubernetes.io/unschedulable:NoSchedule op=Exists
Events:
  Type     Reason   Age                     From     Message
  ----     ------   ----                    ----     -------
  Normal   Pulled   16m (x205 over 18h)     kubelet  (combined from similar events): Successfully pulled image "cr.openfuyao.cn/openfuyao/ascend-image/ascend-k8sdeviceplugin:v6.0.0" in 403ms (403ms including waiting). Image size: 48017174 bytes.
  Warning  BackOff  2m47s (x5216 over 18h)  kubelet  Back-off restarting failed container device-plugin-01 in pod ascend-device-plugin-ll46f_kube-system(8edcd384-ab2d-4998-8077-5ac58801c79e)
  Normal   Pulling  66s (x227 over 19h)     kubelet  Pulling image "cr.openfuyao.cn/openfuyao/ascend-image/ascend-k8sdeviceplugin:v6.0.0"

故障 pod /dev 检查

[root@master1 fuyao-26.3-rc3]# kubectl  -n kube-system exec -it daemonsets/ascend-device-plugin -- ls /dev
Defaulted container "device-plugin-01" out of: device-plugin-01, init-permission (init)
autofs           null               tty10  tty34  tty58    vcs5
bsg              ppp                tty11  tty35  tty59    vcs6
btrfs-control    ptmx               tty12  tty36  tty6     vcsa
bus              pts                tty13  tty37  tty60    vcsa1
core             random             tty14  tty38  tty61    vcsa2
cpu_dma_latency  raw                tty15  tty39  tty62    vcsa3
cuse             relationship_ctrl  tty16  tty4   tty63    vcsa4
davinci0         rfkill             tty17  tty40  tty7     vcsa5
davinci_manager  rtc0               tty18  tty41  tty8     vcsa6
devmm_svm        sda                tty19  tty42  tty9     vcsu
dri              sda1               tty2   tty43  ttyAMA0  vcsu1
fb0              sda2               tty20  tty44  ttyS0    vcsu2
fd               sg0                tty21  tty45  ttyS1    vcsu3
full             sg1                tty22  tty46  ttyS2    vcsu4
fuse             sg2                tty23  tty47  ttyS3    vcsu5
hidraw0          shm                tty24  tty48  uhid     vcsu6
hidraw1          snapshot           tty25  tty49  uinput   vfio
hisi_hdc         sr0                tty26  tty5   urandom  vga_arbiter
hwrng            sr1                tty27  tty50  usbmon0  vhost-net
input            stderr             tty28  tty51  usbmon1  vhost-vsock
kmsg             stdin              tty29  tty52  usbmon2  vport2p1
loop-control     stdout             tty3   tty53  vcs      zero
mapper           termination-log    tty30  tty54  vcs1
mem              tty                tty31  tty55  vcs2
mqueue           tty0               tty32  tty56  vcs3
net              tty1               tty33  tty57  vcs4

故障 pod 驱动检查

[root@master1 fuyao-26.3-rc3]# kubectl  -n kube-system exec -it daemonsets/ascend-device-plugin -- ls -lha /usr/local/Ascend/driver
Defaulted container "device-plugin-01" out of: device-plugin-01, init-permission (init)
total 44K
drwxr-xr-x  8 root root 4.0K Mar 27 08:03 .
drwxr-xr-x  3 root root 4.0K Mar 31 02:34 ..
drwxr-xr-x  2 root root 4.0K Mar 27 08:01 bin
-r--r--r--  1 root root   20 Mar 27 08:01 build.info
dr-xr-x---  2 root root 4.0K Mar 27 08:01 device
dr-x------ 41 root root 4.0K Mar 27 08:01 kernel
drwxr-xr-x  6 root root 4.0K Mar 27 08:01 lib64
-r--r-----  1 root root   56 Mar 27 08:01 scene.info
dr-xr-x---  2 root root 4.0K Mar 27 08:01 script
drwxr-xr-x  2 root root 4.0K Mar 27 08:01 tools
-r--r--r--  1 root root  352 Mar 27 08:03 version.info

故障 pod 日志

[root@master1 ~]# kubectl -n kube-system logs daemonsets/ascend-device-plugin --previous
Defaulted container "device-plugin-01" out of: device-plugin-01, init-permission (init)
[INFO]     2026/03/31 06:46:54.593254 1       hwlog/api.go:108    devicePlugin.log's logger init success
[INFO]     2026/03/31 06:46:54.593449 1       main.go:187    ascend device plugin starting and the version is v6.0.0_linux-aarch64
[INFO]     2026/03/31 06:46:54.593494 1       main.go:188    ascend device plugin starting scene is center
[INFO]     2026/03/31 06:46:54.787930 1       devmanager/devmanager.go:104    the dcmi version is 24.1.rc3
[ERROR]    2026/03/31 06:46:54.788019 1       devmanager/devmanager.go:211    get error card quantity: 0
[ERROR]    2026/03/31 06:46:54.788052 1       devmanager/devmanager.go:195    get card list failed for init
[ERROR]    2026/03/31 06:46:54.788101 1       main.go:203    init devmanager failed, err: auto init failed, err: get card list failed for init

故障 pod 驱动检查

[root@master1 ~]# kubectl -n kube-system exec -it daemonsets/ascend-device-plugin -- bash -c 'find /usr/local/Ascend/driver -name libdcmi.so 2>/dev/null; echo $LD_LIBRARY_PATH'
Defaulted container "device-plugin-01" out of: device-plugin-01, init-permission (init)
/usr/local/Ascend/driver/lib64/driver/libdcmi.so
command terminated with exit code 137
[root@master1 ~]# ps -ef | grep -E 'dmp_daemon|slogd' | grep -v grep
root       21578       1  0 Mar30 ?        00:00:19 /usr/sbin/rsyslogd -n -i/var/run/rsyslogd.pid

检查服务状态?

[root@master1 ~]# systemctl status ascend-dmi
Unit ascend-dmi.service could not be found.
[root@master1 ~]# systemctl status ascend-dkms
Unit ascend-dkms.service could not be found.
[root@master1 ~]# systemctl status npu-smi
Unit npu-smi.service could not be found.
[root@master1 ~]# find / -name dmp_daemon 2>/dev/null
[root@master1 ~]# find / -name slogd 2>/dev/null
[root@master1 ~]# ls -l /var/dmp_daemon /var/slogd 2>/dev/null
[root@master1 ~]# 

dcmi 问题,需硬件排查

检查卡获取

#include <stdlib.h>
#include <stdio.h>
#include "dcmi_interface_api.h"

int my_get_card_list();

int main(int argc,char *argv[])
{
    my_get_card_list();
    return 0;
}

int my_get_card_list()
{
    printf("\n==================================card id info list=========================\n");
    dcmi_init();
    int card_num = 0;
    int card_list[16] = {0};
    int ret = dcmi_get_card_list(&card_num, card_list, 16);
    if (ret != DCMI_OK) {
        printf("dcmi get card list failed ret=%d\n", ret);
    }
    printf("card_num=%d, card_list:[",card_num);
    for (int i = 0; i < card_num; i++) {
        printf("%d ", card_list[i]);
    }
}
cc ./test1.c -o test1 -I /usr/local/dcmi -L /usr/local/dcmi -ldcmi

-I头文件(.h)搜索路径
-L库文件(.so/.a)搜索路径
-l链接的库名(去掉 lib 前缀)
nerdctl run --rm \
  -v /usr/local/Ascend:/usr/local/Ascend \
  -v /usr/local/dcmi:/usr/local/dcmi \
  -v $(pwd):/build \
  ubuntu:18.04 bash -c "
    sed -i -e 's@http*://ports.ubuntu.com/\? @http://10.17.31.217:8081/repository/mirror-ubuntu-ports/@g' \
           -e 's@http*://ports.ubuntu.com@http://10.17.31.217:8081/repository/mirror-ubuntu-ports@g' \
           /etc/apt/sources.list
    apt update && apt install -y gcc
    cd /build
    cc ./test1.c -o test1 \
      -I /usr/local/dcmi \
      -L /usr/local/dcmi \
      -L /usr/local/Ascend/driver/lib64/common \
      -L /usr/local/Ascend/driver/lib64/driver \
      -ldcmi \
      -Wl,-rpath,/usr/local/Ascend/driver/lib64/common \
      -Wl,-rpath,/usr/local/Ascend/driver/lib64/driver \
      -Wl,-rpath,/usr/local/dcmi
  "

分析二进制:

[root@master1 ascend_debug]# ldd ./test1 | grep -i dcmi
        libdcmi.so => /usr/local/Ascend/driver/lib64/driver/libdcmi.so (0x0000ffffa6dd0000)
[root@master1 ascend_debug]# LD_DEBUG=libs ./test1 2>&1 | grep -i dcmi
    284830:     find library=libdcmi.so [0]; searching
    284830:      search path=/usr/local/Ascend/driver/lib64/common/tls/aarch64/atomics:/usr/local/Ascend/driver/lib64/common/tls/aarch64:/usr/local/Ascend/driver/lib64/common/tls/atomics:/usr/local/Ascend/driver/lib64/common/tls:/usr/local/Ascend/driver/lib64/common/aarch64/atomics:/usr/local/Ascend/driver/lib64/common/aarch64:/usr/local/Ascend/driver/lib64/common/atomics:/usr/local/Ascend/driver/lib64/common:/usr/local/Ascend/driver/lib64/driver/tls/aarch64/atomics:/usr/local/Ascend/driver/lib64/driver/tls/aarch64:/usr/local/Ascend/driver/lib64/driver/tls/atomics:/usr/local/Ascend/driver/lib64/driver/tls:/usr/local/Ascend/driver/lib64/driver/aarch64/atomics:/usr/local/Ascend/driver/lib64/driver/aarch64:/usr/local/Ascend/driver/lib64/driver/atomics:/usr/local/Ascend/driver/lib64/driver:/usr/local/dcmi/tls/aarch64/atomics:/usr/local/dcmi/tls/aarch64:/usr/local/dcmi/tls/atomics:/usr/local/dcmi/tls:/usr/local/dcmi/aarch64/atomics:/usr/local/dcmi/aarch64:/usr/local/dcmi/atomics:/usr/local/dcmi            (RUNPATH from file ./test1)
    284830:       trying file=/usr/local/Ascend/driver/lib64/common/tls/aarch64/atomics/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/common/tls/aarch64/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/common/tls/atomics/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/common/tls/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/common/aarch64/atomics/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/common/aarch64/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/common/atomics/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/common/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/driver/tls/aarch64/atomics/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/driver/tls/aarch64/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/driver/tls/atomics/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/driver/tls/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/driver/aarch64/atomics/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/driver/aarch64/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/driver/atomics/libdcmi.so
    284830:       trying file=/usr/local/Ascend/driver/lib64/driver/libdcmi.so
    284830:      search path=/usr/local/Ascend/driver/lib64/common:/usr/local/Ascend/driver/lib64/driver:/usr/local/dcmi/tls/aarch64/atomics:/usr/local/dcmi/tls/aarch64:/usr/local/dcmi/tls/atomics:/usr/local/dcmi/tls:/usr/local/dcmi/aarch64/atomics:/usr/local/dcmi/aarch64:/usr/local/dcmi/atomics:/usr/local/dcmi          (RUNPATH from file ./test1)
    284830:       trying file=/usr/local/dcmi/tls/aarch64/atomics/libc.so.6
    284830:       trying file=/usr/local/dcmi/tls/aarch64/libc.so.6
    284830:       trying file=/usr/local/dcmi/tls/atomics/libc.so.6
    284830:       trying file=/usr/local/dcmi/tls/libc.so.6
    284830:       trying file=/usr/local/dcmi/aarch64/atomics/libc.so.6
    284830:       trying file=/usr/local/dcmi/aarch64/libc.so.6
    284830:       trying file=/usr/local/dcmi/atomics/libc.so.6
    284830:       trying file=/usr/local/dcmi/libc.so.6
    284830:     calling init: /usr/local/Ascend/driver/lib64/driver/libdcmi.so
    284830:     calling fini: /usr/local/Ascend/driver/lib64/driver/libdcmi.so [0]
[root@master1 ascend_debug]# readlink -f /usr/local/dcmi/libdcmi.so
/usr/local/dcmi/libdcmi.so
[root@master1 ascend_debug]# readlink -f /usr/local/Ascend/driver/lib64/driver/libdcmi.so
/usr/local/Ascend/driver/lib64/driver/libdcmi.so
[root@master1 ascend_debug]# sha256sum /usr/local/dcmi/libdcmi.so /usr/local/Ascend/driver/lib64/driver/libdcmi.so
13a38cae84bad0f06367ff9280016e372c0608ca16465b5ae5f000d3844ee401  /usr/local/dcmi/libdcmi.so
13a38cae84bad0f06367ff9280016e372c0608ca16465b5ae5f000d3844ee401  /usr/local/Ascend/driver/lib64/driver/libdcmi.so

跟踪 strace

宿主机跑
strace -f -o /tmp/host.strace -e trace=file,ioctl ./test1
容器里跑
strace -f -o /tmp/container.strace -e trace=file,ioctl ./test1

新增挂载继续跟踪

volumeMounts:
        - name: hdc-basic
          mountPath: /etc/hdcBasic.cfg
          readOnly: true
        - name: localtime
          mountPath: /etc/localtime
          readOnly: true
      volumes:
      - name: hdc-basic
        hostPath:
          path: /etc/hdcBasic.cfg
          type: File
      - name: localtime
        hostPath:
          path: /etc/localtime
          type: File

跟踪并查看日志

kubectl -n kube-system exec -it ascend-device-plugin-69q5t -c device-plugin-01 -- bash

strace -f -o /tmp/container.strace -e trace=file,ioctl ./test1

root@ascend-device-plugin-69q5t:/tmp# strace -f -o /tmp/container.strace -e trace=file,ioctl ./test1

==================================card id info list=========================
card_num=0, card_list:[


root@ascend-device-plugin-69q5t:/tmp# cat /var/log/nputools_LOG_INFO.log > /tmp/nputools_LOG_INFO.log
root@ascend-device-plugin-69q5t:/tmp# cat /var/log/nputools_LOG_ERR.log > /tmp/nputools_LOG_ERR.log
cat: /var/log/nputools_LOG_ERR.log: No such file or directory
root@ascend-device-plugin-69q5t:/tmp# cat /tmp/nputools_LOG_INFO.log 
[2026/04/01 11:18:12][0583][root][127.0.0.1][dcmi_api.c,dcmi_board_init,86]:dcmi board init success. device_count=1.
[2026/04/01 11:18:12][0583][root][127.0.0.1][dcmi_api.c,dcmi_init,119]:dcmi init all success.

检查代码2

#include <stdio.h>
#include <stdlib.h>
#include "dcmi_interface_api.h"

#ifndef DCMI_OK
#define DCMI_OK 0
#endif

/* 头文件里没看到这个声明,手动补一个 */
extern int dcmi_get_card_num_list(int *card_num, int *card_list, int list_length);

static void print_list(const char *name, int ret, int num, int *list) {
    printf("%s ret=%d num=%d list=[", name, ret, num);
    for (int i = 0; i < num; ++i) {
        printf("%d ", list[i]);
    }
    printf("]\n");
}

int main(void) {
    int ret = dcmi_init();
    printf("dcmi_init ret=%d\n", ret);
    if (ret != DCMI_OK) {
        return 1;
    }

    int card_num = 0;
    int card_list[16] = {0};

    ret = dcmi_get_card_list(&card_num, card_list, 16);
    print_list("dcmi_get_card_list", ret, card_num, card_list);

    int card_num2 = 0;
    int card_list2[16] = {0};
    ret = dcmi_get_card_num_list(&card_num2, card_list2, 16);
    print_list("dcmi_get_card_num_list", ret, card_num2, card_list2);

    for (int i = 0; i < card_num && i < 16; ++i) {
        int dev_num = -1;
        ret = dcmi_get_device_num_in_card(card_list[i], &dev_num);
        printf("dcmi_get_device_num_in_card card=%d ret=%d dev_num=%d\n",
               card_list[i], ret, dev_num);
    }

    return 0;
}

主机编译

cc ./test2.c -o test2 -I /usr/local/dcmi -L /usr/local/dcmi -ldcmi

容器编译

nerdctl run --rm \
  -v /usr/local/Ascend:/usr/local/Ascend \
  -v /usr/local/dcmi:/usr/local/dcmi \
  -v $(pwd):/build \
  ubuntu:18.04 bash -c "
    sed -i -e 's@http*://ports.ubuntu.com/\? @http://10.17.31.217:8081/repository/mirror-ubuntu-ports/@g' \
           -e 's@http*://ports.ubuntu.com@http://10.17.31.217:8081/repository/mirror-ubuntu-ports@g' \
           /etc/apt/sources.list
    apt update && apt install -y gcc
    cd /build
    cc ./test2.c -o test2 \
      -I /usr/local/dcmi \
      -L /usr/local/dcmi \
      -L /usr/local/Ascend/driver/lib64/common \
      -L /usr/local/Ascend/driver/lib64/driver \
      -ldcmi \
      -Wl,-rpath,/usr/local/Ascend/driver/lib64/common \
      -Wl,-rpath,/usr/local/Ascend/driver/lib64/driver \
      -Wl,-rpath,/usr/local/dcmi
  "

拷入容器运行

kubectl -n kube-system cp ./test2 ascend-device-plugin-69q5t:/tmp/
# 主机运行
[root@master1 ascend_debug]# ./test2
dcmi_init ret=0
dcmi_get_card_list ret=0 num=1 list=[176 ]
dcmi_get_card_num_list ret=0 num=1 list=[176 ]
dcmi_get_device_num_in_card card=176 ret=0 dev_num=1

# 容器运行
root@ascend-device-plugin-69q5t:/tmp# ./test2 
dcmi_init ret=0
dcmi_get_card_list ret=0 num=0 list=[]
dcmi_get_card_num_list ret=0 num=0 list=[]

虚拟机场景

经过许老师认真定位,最终发现是因为非裸金属环境。虚拟机场景需要定制镜像。

根据官网文档

如果在虚拟机场景下部署Ascend Device Plugin,需要在Ascend Device Plugin的镜像中安装systemd,推荐在Dockerfile中加入RUN apt-get update && apt-get install -y systemd命令进行安装。

为了使用 nerdctl 构建镜像首先安装 buildkit

wegt https://github.com/moby/buildkit/releases/download/v0.29.0/buildkit-v0.29.0.linux-arm64.tar.gz
tar zxvf buildkit-v0.29.0.linux-arm64.tar.gz
cp bin/* /usr/local/bin/

之后找一个新终端启动 buildkit ,这里是为了 nerdctl 构建 image, 如果不需要则不用启动。

buildkitd --oci-worker=false --containerd-worker=true --containerd-worker-namespace=k8s.io 

Dockerfile 如下:

镜像源部分按需修改
FROM hub.oepkgs.net/openfuyao/ascendhub/ascend-k8sdeviceplugin:v6.0.0

# 替换 apt 镜像源
RUN sed -i \
    -e 's@http*://ports.ubuntu.com/\? @http://10.17.31.217:8081/repository/mirror-ubuntu-ports/@g' \
    -e 's@http*://ports.ubuntu.com@http://10.17.31.217:8081/repository/mirror-ubuntu-ports@g' \
    /etc/apt/sources.list

# 安装 systemd
RUN apt-get update && \
    apt-get install -y --no-install-recommends systemd systemd-sysv && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 设置 systemd 为 init
STOPSIGNAL SIGRTMIN+3
STOPSIGNAL SIGRTMIN+3 是告诉容器运行时(containerd/docker)停止这个容器时应该发送哪个信号。
如果你的容器里 不跑 systemd 作为主进程(比如 entrypoint 是业务程序),这行可以删掉,没有任何作用。
如果确实用 systemd 管理容器内服务,保留它能避免 kubectl delete pod 时等待 30 秒超时再强杀的问题。

构建命令如下:

nerdctl build \
  --namespace k8s.io \
  -t hub.oepkgs.net/openfuyao/ascendhub/ascend-k8sdeviceplugin:v6.0.0-systemd \
  -f Dockerfile \
  .

之后将出问题的镜像替换为新构建的镜像即可。

npu-operator 有同样的问题,一样修改即可。

修复确认

最终在 node 中能看到 npu 资源即成功。
[root@master1 ~]# kubectl  describe node master1 
Name:               master1
Roles:              control-plane,master,node,worker
Labels:             accelerator=huawei-Ascend310P
                    beta.kubernetes.io/arch=arm64
                    beta.kubernetes.io/os=linux
...
                    servertype=Ascend310P-8
                    workerselector=dls-worker-node
Annotations:        baseDeviceInfos: {"Ascend310P-0":{"IP":"","SuperDeviceID":0}}
...
Capacity:
  cpu:                    16
  ephemeral-storage:      129724184Ki
  huawei.com/Ascend310P:  1
  hugepages-1Gi:          0
  hugepages-2Mi:          0
  hugepages-32Mi:         0
  hugepages-64Ki:         0
  memory:                 32595632Ki
  pods:                   110
Allocatable:
  cpu:                    16
  ephemeral-storage:      119553807777
  huawei.com/Ascend310P:  1
  hugepages-1Gi:          0
  hugepages-2Mi:          0
  hugepages-32Mi:         0
  hugepages-64Ki:         0
  memory:                 32493232Ki
  pods:                   110
...
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource               Requests       Limits
  --------               --------       ------
  cpu                    15565m (97%)   16910m (105%)
  memory                 17492Mi (55%)  30900Mi (97%)
  ephemeral-storage      0 (0%)         0 (0%)
  hugepages-1Gi          0 (0%)         0 (0%)
  hugepages-2Mi          0 (0%)         0 (0%)
  hugepages-32Mi         0 (0%)         0 (0%)
  hugepages-64Ki         0 (0%)         0 (0%)
  huawei.com/Ascend310P  0              0
...

KDE Plasma6 禁用全局菜单,恢复正常应用菜单

2026-04-01 13:55:30

前情提要

不知道从什么时候开始,KDE Plasma 默认启用类似 macOS 的全局应用菜单。

即应用窗口标题栏下方不显示菜单,而是移动到顶部菜单栏中“全局菜单”小组件中。

但问题是,Linux 桌面生态生态复杂,X11 Wayland Qt GTK 等等技术太过复杂,很难保证常用软件都能够正常显示全局菜单。

比如我最近在使用 Joplin ,就发现除了菜单栏根本找不到任何入口。

于是搜索了一番后,终于找到了关闭全局菜单,恢复正常的应用菜单的方法。

恢复方法

第一步:移除“全局菜单组件”

Edit Mode > Add or Manage Widgets > Global Menu > Remove all instances (button in the top right corner of the widget)

进入编辑模式,添加或管理组件,删除“全局菜单”小组间

image

第二步:移除应用菜单

实测完成第一步即可,第二步按照自己实际情况决定是否要做。

Settings > Colors & Themes > Window Decorations > Configure Titlebar Buttons…

There remove the Application Menu (“Hamburger”) button from your titlebars.

进入设置,颜色与主题,窗口装饰元素,配置菜单栏按钮,将“应用菜单”按钮移除,点击应用,即可。

image

第三步:重启应用

此时应该就能看到应用菜单了,如果看不到再重启一下即可。

image

Refs

终极指南:在 Linux 裸机服务器上快速部署 Moltbot (原 Clawbot) 并集成飞书

2026-01-29 20:00:15

引言

2026 年初,一个名为 Moltbot(前身为 Clawbot)的开源 AI 代理(Agent)框架席卷了开发者社区。该框架允许用户将强大的 AI 模型(例如 OpenAI 的 GPT 系列、Anthropic 的 Claude 等)与 WhatsApp、Telegram、Discord 等日常通讯工具集成,从而通过聊天即可操控电脑、执行任务、获取信息。特斯拉前 AI 主管 Andrej Karpathy 的推荐更是使其迅速走红,其 GitHub 项目在短时间内获得了超过 60,000 个星标。

本指南将提供一份以安全为核心的详尽教程,旨在引导您逐步在 Linux 裸机服务器上安全地完成 Moltbot 的部署。

准备工作

在开始之前,请确保你已具备以下条件:

项目 要求 说明
Linux 服务器 Ubuntu 22.04+ 或其他现代发行版 推荐至少 2GB RAM 和 2 核 CPU。
基础 Linux 知识 熟悉 SSH、命令行操作 本教程将提供所有需要的命令。

第一步:准备服务器环境

基于安全最佳实践,我们强烈建议不要直接使用 root 用户运行任何应用程序。因此,第一步是创建一个专用的非特权用户,并为其授予 sudo 权限。

  1. root 用户 SSH 登录你的服务器
ssh root@your_server_ip
  1. 创建一个新用户(我们称之为 moltbot):
adduser moltbot

系统会提示你为新用户设置密码和其他信息。

  1. 将新用户添加到 sudo,以便执行需要管理员权限的操作:
usermod -aG sudo moltbot
  1. 切换到新用户
su - moltbot
  1. 更新系统软件包
sudo apt update && sudo apt upgrade -y

此后,所有操作都应在该 moltbot 用户下进行。

第二步:安装 Moltbot

Moltbot 的核心依赖是 Node.js (版本 ≥ 22)。官方提供了一个便捷的一键安装脚本,可自动处理相关依赖并完成 Moltbot 的安装。

  1. 执行官方安装脚本
curl -fsSL https://molt.bot/install.sh | bash

该脚本会自动检测您的操作系统,安装适配的 Node.js 版本,并部署 Moltbot 命令行工具(CLI)。

安装成功后,将自动进入交互式配置流程,如下图所示:

图片

第一个选项是风险提示,输入 yes 确认已知晓。

第二步在模式选择中,建议选择 QuickStart 以进行快速配置。

第三步:配置使用 Qwen

在选择模型服务商时,本教程以阿里云的 Qwen(通义千问)为例,其提供充足的免费额度,非常适合初学者入门。待您熟悉系统后,可根据需求更换为其他模型。

选择 Qwen 模型后,终端会提供一个授权链接,请复制并在浏览器中打开。

打开链接后,您会看到授权页面。如果您尚未登录阿里云账户,请根据提示完成登录。

登录成功后,系统会提示您选择具体的 Qwen 模型版本。

此处选择默认模型即可。随后,安装向导会询问是否配置频道(Channel),建议暂时跳过,后续再进行配置。

接着,在技能(Skills)配置步骤中,同样选择 No。

等待安装流程结束,在最后的启动方式选择中,选择 TUI(文本用户界面)。

如果成功进入 TUI 聊天界面,说明 Moltbot 已正确安装。您可以输入 Hello 进行初步测试。

测试无误后,使用 Ctrl+C 组合键退出 TUI 界面,以便进行后续的后台服务配置。

第四步:配置 Moltbot 并启动 Gateway

  1. 检查 Gateway 服务状态

安装向导会自动将 Gateway 配置为系统服务并在后台启动。

clawdbot gateway status

如果服务正常运行,您将看到 active (running) 的状态提示。

服务状态

如果检查状态时发现服务异常(例如 inactivefailed),可以尝试使用内置的诊断工具进行修复:

clawdbot doctor --repair

修复后,再次检查状态,应可看到服务已恢复正常。

服务状态

  1. 配置选项

您可以根据需要编辑 Moltbot 的主配置文件。

使用文本编辑器(如 vimnano)打开配置文件:

sudo vim ~/.clawdbot/clawdbot.json
  1. 重载并重启服务

每次修改配置文件后,需要重载服务以使更改生效。虽然某些版本的 Moltbot 支持自动重载,但手动重启是更可靠的方式。

systemctl --user daemon-reload
clawdbot gateway restart

至此,Moltbot Gateway 已在后台稳定运行,并监听本地端口,等待连接。

第五步:访问后台

Moltbot 自带一个 Web UI 用于管理和测试。运行以下命令可获取访问方式:

clawdbot dashboard

命令会输出一段 SSH 端口转发指令,格式如下:

后台访问方法

在您的本地电脑(而非服务器)上打开一个终端,并执行上述 SSH 命令。该命令会将服务器的 Web UI 端口 18789 映射到您本地的同名端口。

ssh -N -L 18789:127.0.0.1:18789 [email protected] -p xxx

命令运行后,在本地浏览器访问 http://127.0.0.1:18789 即可打开 Web UI 。

您可以发送一条 Hello 消息进行测试,如果收到回复,则说明一切正常。

后台界面

第六步:接入飞书

首先,在服务器上为 Moltbot 安装飞书插件:

clawdbot plugins install @m1heng-clawd/feishu

接下来,登录飞书开放平台,进入「开发者后台」,点击「创建企业自建应用」。

填写应用名称和描述后,完成创建。

创建成功后,进入应用的「凭据与基础信息」页面,复制并妥善保存 App ID 和 App Secret,它们将在后续配置中用到。

然后添加机器人,如下操作

暂时停留在飞书后台,我们先返回服务器终端,完成 Moltbot 的飞书相关配置。

飞书的其他配置先暂停,回到服务器配置 Clawdbot 的飞书参数

添加飞书配置

clawdbot config set channels.feishu.appId "飞书 app id"

clawdbot config set channels.feishu.appSecret "飞书 app secret"

clawdbot config set channels.feishu.enabled true

# 推荐使用 websocket
clawdbot config set channels.feishu.connectionMode websocket

clawdbot config set channels.feishu.dmPolicy pairing

clawdbot config set channels.feishu.groupPolicy allowlist

clawdbot config set channels.feishu.requireMention true

配置完成之后,重启

clawdbot gateway restart

重启完成后回到飞书,找到「事件和回调」,选择长连接模式,如下图

如果配置成功,说明连接已建立。继续下面的配置,添加事件,选择「接收消息」事件

事件添加完成之后,还需要开通权限,有以下权限全部勾选

权限 Scope(范围) Description(说明)
contact:user.base:readonly 用户信息 获取基础用户信息
im:message 消息 全部勾选 发送和接收消息

如下图

以上步骤全部完成后,即可与机器人对话。但在此之前需要先创建一个版本

注意:每次修改配置后都需要重新发布版本,建议全部配置完成后再统一发布。

发布完成后,回到飞书客户端,可以看到应用已上线,点击打开应用

向机器人发送 Hello,即可收到 Moltbot 的回复

恭喜您!至此,您已成功在 Linux 服务器上部署了 Moltbot,并将其与飞书集成。现在您可以开始探索其强大的功能,或根据官方文档进行更深度的定制。如果在部署过程中遇到任何问题,欢迎留言交流。

常用命令

# 检查常见安全问题
clawdbot security audit

# 自动修复文件权限等问题
clawdbot security audit --fix

# 查看 Moltbot 日志
clawdbot logs --follow

参考文献

Windows 配置 Claude Code 解决 settings.json 不生效

2026-01-09 16:28:00

TL;DR

默认情况下 Windows 安装的 Claude Code 会从这个位置读取配置:

C:\Users\<YOUR_NAME>\.claude

其他系统则类似的找到 ~/.claude 路径。

官方流程在安装结束后就完成了,可以直接登录使用。如果需要修改配置将 Claude Code 接入第三方 API,就需要修改这里的 settings.json 配置文件,可以使用 CC-Switch 或是手动编写,但是修改后会发现不生效。

经过调研,发现是最新版的 Claude Code 修改了一个参数,导致启动时一定要登录,这里可以手动修改一下 C:\Users\<YOUR_NAME>\.claude.json 中的这个参数,即可正常使用:

hasCompletedOnboarding: true

将配置中的 false 改为 true ,再重新运行 Claude Code 即可。

这个问题卡了我两天,一度打算放弃回到其他 OS,最后终于在 这里 找到了答案,因此特别记录一下。

Refs

Windows 配置 Claude Code 全流程

2026-01-09 16:22:00

今天终于跑通了 Windows 下运行 Claoude Code 的全流程,不借助 WSL ,原生运行。起因是自己需要一个可以长期运行任务的云桌面,这方面还是 Windows 最好用。不得不说相比于 Linux/macOSWindows 下运行 Claude Code 实在太多坑了。

感谢 LD 巨佬 哈雷彗星《 Claude Code 终极版 FAQ 指南 》 ,在这份指南的指导下,还有开源社区朋友的帮助下,终于跑通了全流程,在这里记录一下,避免更多的朋友踩坑。

ClaudeCode

环境说明

先说一下我的环境:

  • OS: Windows 10 Enterprise LTSC 2021
  • Shell: PowerShell 5 -> PowerShell 7

我是在全新安装的 Windows 10 Enterprise LTSC 2021 系统中进行,使用系统自带的 PowerShell 5 开始 ,流程中会安装最新的 PoserShell 7 并使用 PS7 完成后续。根据论坛大佬的说法,PS7 很好用,自带的 PS5 不好用,因此下面的流程包含了安装 PS7 的流程,大家可以自己体验一下。

主要流程

以下内容主要来自 《 Claude Code 终极版 FAQ 指南 》 和实践补充。

打开 PowerShell 5 并安装 WinGet:

$progressPreference = 'silentlyContinue'
Install-PackageProvider -Name NuGet -Force | Out-Null
Install-Module -Name Microsoft.WinGet.Client -Force -Repository PSGallery | Out-Null
Write-Host "Using Repair-WinGetPackageManager cmdlet to bootstrap WinGet..."
Repair-WinGetPackageManager -AllUsers

PoserShell 5 中使用 WinGet 安装 PoserShell 7

winget install Microsoft.PowerShell

打开 PoserShell 7 并使用 winget 安装其他依赖,后续全部在 PS7 中进行:


# 必须,安装 fnm 用于管理 node 环境,或使用现有环境
winget install Schniz.fnm
# 可选,安装 Git
winget install --id Git.Git -e --source winget
# 可选,安装 notepad4
winget install zufuliu.notepad4
# 可选,安装 Windows Terminal
winget install -e --id Microsoft.WindowsTerminal
# 可选,安装 Notepad++
winget install -e --id Notepad++.Notepad++

下面使用 fnm 安装特定版本的 node 运行环境,首先需要对 FNM 给予一个环境启动,否则安装的 node 无法使用,因此首先预配置环境:

New-Item –Path $Profile –Type File –Force
notepad $profile

之后将以下内容写入该文件并保存:

fnm env --use-on-cd --shell powershell | Out-String | Invoke-Expression

下面开始正式安装 nodejs:

fnm install lts/krypton
fnm use lts/krypton

全局安装 Claude Code:

npm install -g @anthropic-ai/claude-code

之后就可以愉快的使用 Claude Code 了。

Claude Code  在 Windows PowerShell7 运行

常见问题

配置 settings.json 不生效

默认情况下这样安装的 Claude Code 会从这个位置读取配置:

C:\Users\<YOUR_NAME>\.claude

官方流程在安装结束后就完成了,可以直接登录使用。如果你需要修改配置将 Claude Code 接入第三方 API,就需要修改这里的 settings.json 配置文件,可以使用 CC-Switch 或是手动编写,但是修改后会发现不生效。

经过调研,发现是最新版的 Claude Code 修改了一个参数,导致启动时一定要登录,这里可以手动修改一下 C:\Users\<YOUR_NAME>\.claude.json 中的这个参数,即可正常使用:

hasCompletedOnboarding: true

将配置中的 false 改为 true ,再重新运行 Claude Code 即可。

这个问题卡了我两天,一度打算放弃回到其他 OS,最后终于在 这里 找到了答案,因此特别记录一下。

Refs