我也好奇ll-box是怎么和要运行的软件一起放在一个可执行文件里面的。

集成了运行环境的打包方式??
算了,不了解,坐等大佬解答。
我也好奇ll-box是怎么和要运行的软件一起放在一个可执行文件里面的。

集成了运行环境的打包方式??
算了,不了解,坐等大佬解答。
我也好奇ll-box是怎么和要运行的软件一起放在一个可执行文件里面的。

集成了运行环境的打包方式??
算了,不了解,坐等大佬解答。
果然秘密在ll-builder里面 涉及uab构建
从面向玲珑构建的项目中创建出一个能够运行的uab文件需要以下几个配置文件:
如果只是将项目导出成uab用来向玲珑商店提交应用,并不需要其能够运行,并不需要提供 loader和extra-files.txt
loader的编写参考:
#!/bin/env sh
APPID=org.deepin.demo
./ll-box $APPID $PWD /opt/apps/$APPID/files/bin/demo
传递给ll-box的最后一个参数为需要在容器中运行的二进制。
玲珑的容器貌似就在包含包里面?
distrobox 是一个发行版一个容器,而一般的容器化包管理器是一个应用一个容器。docker 和 podman 本来也是应用级容器,发行版的 oci 容器较为常见的用途是作为构建其他容器的基础,只不过 distrobox 提供了一种便捷的直接使用发行版容器的方式,并且支持在其中运行桌面应用。
distrobox 是一个发行版一个容器,而一般的容器化包管理器是一个应用一个容器。docker 和 podman 本来也是应用级容器,发行版的 oci 容器较为常见的用途是作为构建其他容器的基础,只不过 distrobox 提供了一种便捷的直接使用发行版容器的方式,并且支持在其中运行桌面应用。
感谢大佬的答疑解惑!
突然感觉一下子有趣了起来!
你可以strace看一下,我这边大概猜测原理是这样的
execve("./com.163.music_1.2.1.1_x86_64.uab", ["./com.163.music_1.2.1.1_x86_64.u"...], 0x7ffe66e768a0 /* 58 vars */) = 0
brk(NULL) = 0x1b58000
brk(0x1b59240) = 0x1b59240
arch_prctl(ARCH_SET_FS, 0x1b58900) = 0
uname({sysname="Linux", nodename="zyc-Laptop", ...}) = 0
set_tid_address(0x1b58bd0) = 1087093
set_robust_list(0x1b58be0, 24) = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x4f0ff0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x4f05d0}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x4f1080, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x4f05d0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
readlink("/proc/self/exe", "/tmp/MicrosoftEdgeDownloads/859e"..., 4096) = 97
brk(0x1b7a240) = 0x1b7a240
brk(0x1b7b000) = 0x1b7b000
futex(0x639ecc, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x639ed8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
prctl(PR_SET_PDEATHSIG, SIGKILL) = 0
lstat("/proc", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
lstat("/proc/self", {st_mode=S_IFLNK|0777, st_size=0, ...}) = 0
readlink("/proc/self", "1087093", 4095) = 7
lstat("/proc/1087093", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
lstat("/proc/1087093/exe", {st_mode=S_IFLNK|0777, st_size=0, ...}) = 0
readlink("/proc/1087093/exe", "/tmp/MicrosoftEdgeDownloads/859e"..., 4095) = 97
lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=106496, ...}) = 0
lstat("/tmp/MicrosoftEdgeDownloads", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
lstat("/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
lstat("/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab", {st_mode=S_IFREG|0755, st_size=135758176, ...}) = 0
stat("/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab", {st_mode=S_IFREG|0755, st_size=135758176, ...}) = 0
openat(AT_FDCWD, "/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=135758176, ...}) = 0
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0\360X@\0\0\0\0\0"..., 4096) = 4096
lseek(3, 0, SEEK_SET) = 0
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0\360X@\0\0\0\0\0"..., 4096) = 4096
close(3) = 0
stat("/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab", {st_mode=S_IFREG|0755, st_size=135758176, ...}) = 0
gettimeofday({tv_sec=1686762217, tv_usec=997983}, NULL) = 0
getpid() = 1087093
mkdir("/tmp/uab-cOZdva", 0700) = 0
getpid() = 1087093
semget(0x109675, 1, IPC_CREAT|0666) = 9
semctl(9, 0, SETVAL, NULL) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x1b58bd0) = 1087094
semop(9, [{0, -1, SEM_UNDO}], 1) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1087094, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
stat("/tmp/uab-cOZdva/loader", {st_mode=S_IFREG|0755, st_size=300, ...}) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x1b58bd0) = 1087098
wait4(-1, NULL, 0, NULL) = 1087094
wait4(-1, NULL, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
wait4(-1, NULL, 0, NULL) = 1087098
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1087098, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, NULL, 0, NULL) = -1 ECHILD (没有子进程)
umount2("/tmp/uab-cOZdva", 0) = -1 EPERM (不允许的操作)
rt_sigaction(SIGINT, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x4f05d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x4f05d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
clone(child_stack=NULL, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0x7ffe1ac4c0dc) = 1088255
wait4(1088255, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 1088255
rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x4f05d0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x4f05d0}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1088255, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
exit_group(0) = ?
+++ exited with 0 +++
这个就可以看出是mount上去的,而且没解包直接mount,看起来这个bundle里还自带了某种FUSE文件系统的库!
: mount | grep uab
/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab on /tmp/uab-rshHrb type fuse.com.163.music_1.2.1.1_x86_64.uab (ro,nosuid,nodev,relatime,user_id=1000,group_id=1000)
zyc@zyc-Laptop:/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c$ tree /tmp/uab-rshHrb -L 2
/tmp/uab-rshHrb
├── busybox
├── entries
│ ├── applications
│ ├── autostart
│ ├── icons
│ ├── plugins
│ └── services
├── files
│ ├── bin
│ ├── doc
│ ├── include
│ ├── lib
│ ├── netease-cloud-music
│ ├── netease-cloud-music.bash
│ ├── plugins
│ └── share
├── info.json
├── ll-box
└── loader
13 directories, 6 files
你可以strace看一下,我这边大概猜测原理是这样的
execve("./com.163.music_1.2.1.1_x86_64.uab", ["./com.163.music_1.2.1.1_x86_64.u"...], 0x7ffe66e768a0 /* 58 vars */) = 0
brk(NULL) = 0x1b58000
brk(0x1b59240) = 0x1b59240
arch_prctl(ARCH_SET_FS, 0x1b58900) = 0
uname({sysname="Linux", nodename="zyc-Laptop", ...}) = 0
set_tid_address(0x1b58bd0) = 1087093
set_robust_list(0x1b58be0, 24) = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x4f0ff0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x4f05d0}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x4f1080, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x4f05d0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
readlink("/proc/self/exe", "/tmp/MicrosoftEdgeDownloads/859e"..., 4096) = 97
brk(0x1b7a240) = 0x1b7a240
brk(0x1b7b000) = 0x1b7b000
futex(0x639ecc, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x639ed8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
prctl(PR_SET_PDEATHSIG, SIGKILL) = 0
lstat("/proc", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
lstat("/proc/self", {st_mode=S_IFLNK|0777, st_size=0, ...}) = 0
readlink("/proc/self", "1087093", 4095) = 7
lstat("/proc/1087093", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
lstat("/proc/1087093/exe", {st_mode=S_IFLNK|0777, st_size=0, ...}) = 0
readlink("/proc/1087093/exe", "/tmp/MicrosoftEdgeDownloads/859e"..., 4095) = 97
lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=106496, ...}) = 0
lstat("/tmp/MicrosoftEdgeDownloads", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
lstat("/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
lstat("/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab", {st_mode=S_IFREG|0755, st_size=135758176, ...}) = 0
stat("/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab", {st_mode=S_IFREG|0755, st_size=135758176, ...}) = 0
openat(AT_FDCWD, "/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=135758176, ...}) = 0
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0\360X@\0\0\0\0\0"..., 4096) = 4096
lseek(3, 0, SEEK_SET) = 0
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0\360X@\0\0\0\0\0"..., 4096) = 4096
close(3) = 0
stat("/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab", {st_mode=S_IFREG|0755, st_size=135758176, ...}) = 0
gettimeofday({tv_sec=1686762217, tv_usec=997983}, NULL) = 0
getpid() = 1087093
mkdir("/tmp/uab-cOZdva", 0700) = 0
getpid() = 1087093
semget(0x109675, 1, IPC_CREAT|0666) = 9
semctl(9, 0, SETVAL, NULL) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x1b58bd0) = 1087094
semop(9, [{0, -1, SEM_UNDO}], 1) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1087094, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
stat("/tmp/uab-cOZdva/loader", {st_mode=S_IFREG|0755, st_size=300, ...}) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x1b58bd0) = 1087098
wait4(-1, NULL, 0, NULL) = 1087094
wait4(-1, NULL, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
wait4(-1, NULL, 0, NULL) = 1087098
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1087098, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, NULL, 0, NULL) = -1 ECHILD (没有子进程)
umount2("/tmp/uab-cOZdva", 0) = -1 EPERM (不允许的操作)
rt_sigaction(SIGINT, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x4f05d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x4f05d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
clone(child_stack=NULL, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0x7ffe1ac4c0dc) = 1088255
wait4(1088255, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 1088255
rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x4f05d0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x4f05d0}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1088255, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
exit_group(0) = ?
+++ exited with 0 +++
这个就可以看出是mount上去的,而且没解包直接mount,看起来这个bundle里还自带了某种FUSE文件系统的库!
: mount | grep uab
/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c/com.163.music_1.2.1.1_x86_64.uab on /tmp/uab-rshHrb type fuse.com.163.music_1.2.1.1_x86_64.uab (ro,nosuid,nodev,relatime,user_id=1000,group_id=1000)
zyc@zyc-Laptop:/tmp/MicrosoftEdgeDownloads/859e6a23-5083-4324-81b5-183beacf3a0c$ tree /tmp/uab-rshHrb -L 2
/tmp/uab-rshHrb
├── busybox
├── entries
│ ├── applications
│ ├── autostart
│ ├── icons
│ ├── plugins
│ └── services
├── files
│ ├── bin
│ ├── doc
│ ├── include
│ ├── lib
│ ├── netease-cloud-music
│ ├── netease-cloud-music.bash
│ ├── plugins
│ └── share
├── info.json
├── ll-box
└── loader
13 directories, 6 files

太厉害了,分析的太好了,玲珑的确使用了fuse
可加载可执行的镜像,看起来bundle包本身是elf文件,所以才有loader加载器?
thinkyoung@NUC:~/下载$ readelf -h ./com.xunlei.download_1.0.0.2_x86_64.uab
ELF 头:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
类别: ELF64
数据: 2 补码,小端序 (little endian)
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI 版本: 0
类型: EXEC (可执行文件)
系统架构: Advanced Micro Devices X86-64
版本: 0x1
入口点地址: 0x4058f0
程序头起点: 64 (bytes into file)
Start of section headers: 2324960 (bytes into file)
标志: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 8
Size of section headers: 64 (bytes)
Number of section headers: 30
Section header string table index: 29
而loader本身就是个sh文件
loader的编写参考:
#!/bin/env sh
APPID=org.deepin.demo
./ll-box $APPID $PWD /opt/apps/$APPID/files/bin/demo
同时把ll-box封装进镜像,直接用ll-box运行容器
ps:
我刚看一个sh+tar/img合包成可执行bin的例子,这个原理很像win的捆木马原理,这个实现比较简单,也很好玩
之前我就想简单实现下苹果dmg那种包,可加载可执行磁盘镜像,双击直接挂载,直接就能使用。
Popular Events
More
突然看到玲珑linglong有了离线bundle , 直接运行 ,感觉好神奇 , 就想看看玲珑到底底层怎么实现的!
后来发现玲珑 与 distrobox ,看似没啥关系,其实虽不同,但还有那么点异曲同工之妙!
1.玲珑的外文介绍 是 linglong is the container application toolkit of deepin. Standard oci runtime
从源码看,小白楼主认为,玲珑自己完整实现了runcpp(我起的名字哈,c++版的runc),直接用runcpp调用了oci容器
2.distrobox的英文介绍 是 Distrobox is a wrapper for
podmanordocker(whatever you prefer) ,从源码看,小白楼主认为Distrobox只是
podmanordocker的上层封装调用,而podmanordocker原理就是它最后的底层用runc调用了oci容器因为我代码水平有限,我也有很多弄懂的地方,求大神指导!
1.oci容器也是有镜像文件的,distrobox 是podman pull拉取的,生成容器文件,而玲珑的容器文件在哪呢?
2.离线bundle直接运行,很像appimage,而appimage用了linuxdeploy封装了启动器实现,玲珑离线包uab是怎么实现的呢?貌似这个包是UOS包吧?看看UOS打包工具???