如何把 pgrep 输出结果中需要用单引号包起来的参数包起来? - V2EX
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
wniming
V2EX    Linux

如何把 pgrep 输出结果中需要用单引号包起来的参数包起来?

  •  
  •   wniming Jul 27, 2025 2355 views
    This topic created in 290 days ago, the information mentioned may be changed or developed.

    比如有如下 qemu 的命令行:

    qemu-system-x86_64 \ -machine q35,accel=kvm \ -cpu host \ -m 1G \ -kernel /home/d/kernel/kernel \ -initrd /home/d/rd/initramfs.cpio.gz \ -append 'cOnsole=ttyS0 test="11 22"' \ -netdev '{"type":"tap","vhost":true,"ifname":"eth_0","id":"hostnet0","script":"","downscript":""}' \ -device '{"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:c0:45:c7"}' \ -nographic 

    上述命令的参数的格式是有效的,但是如果命令执行后通过 pgrep 查询命令行字符串,查询出的结果会把单引号去掉:

    d@develop:~$ pgrep -af qemu-system-x86_64 | perl -0pe 's/ -/ \\\n-/g' 19754 qemu-system-x86_64 \ -machine q35,accel=kvm \ -cpu host \ -m 1G \ -kernel /home/d/kernel/kernel \ -initrd /home/d/rd/initramfs.cpio.gz \ -append cOnsole=ttyS0 test="11 22" \ -netdev {"type":"tap","vhost":true,"ifname":"eth_0","id":"hostnet0","script":"","downscript":""} \ -device {"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:c0:45:c7"} \ -nographic 

    去掉单引号的命令无法直接放到 shell 里去执行,我想找到一个通用的办法(不要仅限于 qemu 的参数)把 pgrpe 输出的命令行字符串中需要用单引号包起来的参数用单引号包起来,使其结果和最初执行的命令行字符串完全一样,问了 ai ,ai 解决不了,再次在这里求助 v 友。

    Supplement 1    Jul 27, 2025

    #7 楼给出的方法管用,这里备份一下:

    #!/usr/bin/env python3 import sys import shlex def get_cmdline(pid): with open(f"/proc/{pid}/cmdline") as f: raw = f.read() parts = raw.strip("\0).split("\0") return shlex.join(parts) def main(): if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} <pid>", file=sys.stderr) sys.exit(1) pid = sys.argv[1] print(get_cmdline(pid)) if __name__ == "__main__": main() 
    11 replies    2025-07-28 09:44:20 +08:00
    julyclyde
        1
    julyclyde  
       Jul 27, 2025
    你去/proc/pid/cmdline 里边按照\0 重新组装一下命令行吧
    wniming
        2
    wniming  
    OP
       Jul 27, 2025
    @julyclyde 能具体一点吗?我想当伸手党。。。。

    我自己简单研究了一下,你说的这种方法和 pgrep 没有什么区别:

    d@develop:~$ cat /proc/19754/cmdline | xargs -0 echo | perl -0pe 's/ -/ \\\n-/g'
    qemu-system-x86_64 \
    -machine q35,accel=kvm \
    -cpu host \
    -m 1G \
    -kernel /home/d/kernel/kernel \
    -initrd /home/d/rd/initramfs.cpio.gz \
    -append cOnsole=ttyS0 test="11 22" \
    -netdev {"type":"tap","vhost":true,"ifname":"eth_0","id":"hostnet0","script":"","downscript":""} \
    -device {"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:c0:45:c7"} \
    -nographic
    julyclyde
        3
    julyclyde  
       Jul 27, 2025
    @wniming 其实按说你可以无脑把里边每个字段都加上引号吧?

    你下一步打算怎么使用这个内容?
    billlee
        4
    billlee  
       Jul 27, 2025
    别用 shell 了,用 python 调 os.execvp, 把参数用数组的形式传进去,就不需要引号和转义。
    wniming
        5
    wniming  
    OP
       Jul 27, 2025
    @julyclyde #3 是的,最简单的方式就是每个选项和参数都用单引号包起来,但是这样不美观,我是想把命令行存到日志文件里,就像 libvirt 那样,libvirt 就把日志里的 qemu 命令行格式化成了我想要的效果:

    /usr/bin/qemu-system-x86_64 \
    -name guest=win11-23h2,debug-threads=on \
    -S \
    -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain-9-win11-23h2/master-key.aes"}' \
    -blockdev '{"driver":"file","filename":"/usr/share/edk2/ovmf/OVMF_CODE_4M.qcow2","node-name":"libvirt-pflash0-storage","auto-read-only":true,"discard":"unmap"}' \
    -blockdev '{"node-name":"libvirt-pflash0-format","read-only":true,"driver":"qcow2","file":"libvirt-pflash0-storage","backing":null}' \
    -blockdev '{"driver":"file","filename":"/var/lib/libvirt/qemu/nvram/win11-23h2_VARS.qcow2","node-name":"libvirt-pflash1-storage","auto-read-only":true,"discard":"unmap"}' \
    -blockdev '{"node-name":"libvirt-pflash1-format","read-only":false,"driver":"qcow2","file":"libvirt-pflash1-storage","backing":null}' \
    -machine pc-q35-8.2,usb=off,vmport=off,smm=on,dump-guest-core=off,memory-backend=pc.ram,pflash0=libvirt-pflash0-format,pflash1=libvirt-pflash1-format,hpet=off,acpi=on \
    -accel kvm \
    -cpu host,migratable=on,host-phys-bits=on,host-phys-bits-limit=39 \
    -m size=16777216k \
    -object '{"qom-type":"memory-backend-memfd","id":"pc.ram","hugetlb":true,"hugetlbsize":1073741824,"share":true,"x-use-canonical-path-for-ramblock-id":false,"prealloc":true,"size":17179869184}' \
    -overcommit mem-lock=off \
    -smp 8,sockets=1,dies=1,clusters=1,cores=8,threads=1 \
    -uuid a7849adb-a74b-406-a0a6-738c5e689a8a \
    -no-user-config \
    -nodefaults \
    -chardev socket,id=charmonitor,fd=23,server=on,wait=off \
    -mon chardev=charmonitor,id=monitor,mode=control \
    -rtc base=utc,driftfix=slew \
    -global kvm-pit.lost_tick_policy=delay \
    -no-shutdown \
    -global ICH9-LPC.disable_s3=1 \
    -global ICH9-LPC.disable_s4=1 \
    -boot menu=on,strict=on \
    -device '{"driver":"pcie-root-port","port":16,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x2"}' \
    -device '{"driver":"pcie-root-port","port":17,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x2.0x1"}' \
    -device '{"driver":"pcie-root-port","port":18,"chassis":3,"id":"pci.3","bus":"pcie.0","addr":"0x2.0x2"}' \
    -device '{"driver":"pcie-root-port","port":19,"chassis":4,"id":"pci.4","bus":"pcie.0","addr":"0x2.0x3"}' \
    -device '{"driver":"pcie-root-port","port":20,"chassis":5,"id":"pci.5","bus":"pcie.0","addr":"0x2.0x4"}' \
    -device '{"driver":"pcie-root-port","port":21,"chassis":6,"id":"pci.6","bus":"pcie.0","addr":"0x2.0x5"}' \
    -device '{"driver":"pcie-root-port","port":22,"chassis":7,"id":"pci.7","bus":"pcie.0","addr":"0x2.0x6"}' \
    -device '{"driver":"pcie-root-port","port":23,"chassis":8,"id":"pci.8","bus":"pcie.0","addr":"0x2.0x7"}' \
    -device '{"driver":"pcie-root-port","port":24,"chassis":9,"id":"pci.9","bus":"pcie.0","multifunction":true,"addr":"0x3"}' \
    -device '{"driver":"pcie-root-port","port":25,"chassis":10,"id":"pci.10","bus":"pcie.0","addr":"0x3.0x1"}' \
    -device '{"driver":"pcie-root-port","port":26,"chassis":11,"id":"pci.11","bus":"pcie.0","addr":"0x3.0x2"}' \
    -device '{"driver":"pcie-root-port","port":27,"chassis":12,"id":"pci.12","bus":"pcie.0","addr":"0x3.0x3"}' \
    -device '{"driver":"pcie-root-port","port":28,"chassis":13,"id":"pci.13","bus":"pcie.0","addr":"0x3.0x4"}' \
    -device '{"driver":"pcie-root-port","port":29,"chassis":14,"id":"pci.14","bus":"pcie.0","addr":"0x3.0x5"}' \
    -device '{"driver":"pcie-root-port","port":8,"chassis":15,"id":"pci.15","bus":"pcie.0","addr":"0x1"}' \
    -device '{"driver":"pcie-pci-bridge","id":"pci.16","bus":"pci.12","addr":"0x0"}' \
    -device '{"driver":"qemu-xhci","p2":15,"p3":15,"id":"usb","bus":"pci.2","addr":"0x0"}' \
    -device '{"driver":"virtio-scsi-pci","id":"scsi0","bus":"pci.7","addr":"0x0"}' \
    -device '{"driver":"virtio-serial-pci","id":"virtio-serial0","bus":"pci.3","addr":"0x0"}' \
    -blockdev '{"driver":"host_device","filename":"/dev/thin/win11_23h2","aio":"native","node-name":"libvirt-1-storage","read-only":false,"discard":"unmap","cache":{"direct":true,"no-flush":false}}' \
    -device '{"driver":"virtio-blk-pci","bus":"pci.4","addr":"0x0","drive":"libvirt-1-storage","id":"virtio-disk0","bootindex":1,"write-cache":"on"}' \
    -netdev '{"type":"tap","fd":"24","vhost":true,"vhostfd":"32","id":"hostnet0"}' \
    -device '{"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:1a:14:2d","bus":"pci.1","addr":"0x0"}' \
    -netdev '{"type":"tap","fd":"33","vhost":true,"vhostfd":"34","id":"hostnet1"}' \
    -device '{"driver":"virtio-net-pci","netdev":"hostnet1","id":"net1","mac":"52:54:00:e1:84:76","bus":"pci.11","addr":"0x0"}' \
    -chardev spicevmc,id=charchannel0,name=vdagent \
    -device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":2,"chardev":"charchannel0","id":"channel0","name":"com.redhat.spice.0"}' \
    -chardev socket,id=charchannel1,fd=22,server=on,wait=off \
    -device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel1","id":"channel1","name":"org.qemu.guest_agent.0"}' \
    -audiodev '{"id":"audio1","driver":"spice"}' \
    -spice port=5900,addr=0.0.0.0,disable-ticketing=on,image-compression=off,seamless-migration=on \
    -global ICH9-LPC.noreboot=off \
    -watchdog-action reset \
    -chardev spicevmc,id=charredir0,name=usbredir \
    -device '{"driver":"usb-redir","chardev":"charredir0","id":"redir0","bus":"usb.0","port":"2"}' \
    -chardev spicevmc,id=charredir1,name=usbredir \
    -device '{"driver":"usb-redir","chardev":"charredir1","id":"redir1","bus":"usb.0","port":"3"}' \
    -chardev spicevmc,id=charredir2,name=usbredir \
    -device '{"driver":"usb-redir","chardev":"charredir2","id":"redir2","bus":"usb.0","port":"4"}' \
    -chardev spicevmc,id=charredir3,name=usbredir \
    -device '{"driver":"usb-redir","chardev":"charredir3","id":"redir3","bus":"usb.0","port":"5"}' \
    -device '{"driver":"vfio-pci","host":"0000:08:00.0","id":"hostdev0","bus":"pci.5","addr":"0x0","romfile":"/home/d/.local/share/libvirt/rom/Navi_23.rom"}' \
    -device '{"driver":"vfio-pci","host":"0000:08:00.1","id":"hostdev1","bus":"pci.8","addr":"0x0"}' \
    -object '{"qom-type":"rng-random","id":"objrng0","filename":"/dev/urandom"}' \
    -device '{"driver":"virtio-rng-pci","rng":"objrng0","id":"rng0","bus":"pci.6","addr":"0x0"}' \
    -device '{"driver":"usb-host","hostbus":1,"hostport":"7","bus":"usb.0"}' \
    -device '{"driver":"usb-host","hostbus":1,"hostport":"11","bus":"usb.0"}' \
    -device '{"driver":"usb-host","hostbus":1,"hostport":"10.4","bus":"usb.0"}' \
    -device '{"driver":"usb-host","hostbus":1,"hostport":"10.2","bus":"usb.0"}' \
    -sandbox off \
    -msg timestamp=on

    只把需要用单引号包起来的参数用单引包起来。
    wniming
        6
    wniming  
    OP
       Jul 27, 2025
    @billlee 我是想把 qemu 的命令行保存到文件里
    sunfkny
        7
    sunfkny  
       Jul 27, 2025   1
    https://gist.github.com/sunfkny/90f4a99c7444a840bb5f651c758a38f3
    还得是 python, 核心就是\0 分割 cmdline 之后 shlex.join
    wniming
        8
    wniming  
    OP
       Jul 27, 2025
    @sunfkny 谢谢,完美解决
    billlee
        9
    billlee  
       Jul 27, 2025
    @wniming 只用单引号包起来是不能处理所有情况的,因为参数里可能本身就有单引号。如果需求只是“保存”,那按照 /proc/$pid/cmdline 原样保存就行了。如果其实你需要的是转换成 shell 格式,那需要遍历每个参数,对参数做 shell escape
    guanzhangzhang
        10
    guanzhangzhang  
       Jul 28, 2025
    xargs -0 /proc/<pid>/cmdline > result.txt
    guanzhangzhang
        11
    guanzhangzhang  
       Jul 28, 2025
    @guanzhangzhang xargs -0 < /proc/<pid>/cmdline > result.txt
    About     Help     Advertise     Blog     API     FAQ     Solana     1028 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 38ms UTC 22:34 PVG 06:34 LAX 15:34 JFK 18:34
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86