yuandi42 发表于 2022-4-1 00:44

linux shell script 求解惑

https://img1.doubanio.com/view/status/l/public/395c6f67fb6abd8.webp
https://s3.bmp.ovh/imgs/2022/04/01/dd0f6c259e72b65a.jpg

先声明我不是超能力者,最多写点 python bash 这种低等胶水语言。所以我的问题可能非常非常愚蠢,希望诸位超能力者多多海涵。
最近在折腾linux桌面,写状态栏脚本的时候遇到了一点问题。如上图所示,我的状态栏其实是一堆 bash 脚本,设置鼠标动作可以触发命令。右边的脚本是显示电池状态的,左击会在vim里打开这个脚本。但是由于这个脚本打开了一个vim,在我关闭这个vim之前它会一直悬挂在这里不会更新状态,像左边这个htop tree显示的一样。这对于一个按时间周期更新电池状态的脚本来说不算大问题,但对于其他脚本来说可能就不是这么一回事了。

我想知道有没有方法让脚本A运行另一个脚本或者命令B,但不在A下运行,i.e., A的剩余部分也能直接运行下去,A重启或者关闭也不会导致B关闭(我不知道我的表述是否正确)。在这里&显然是不管用的,nohup和disown好像也不对。我浅薄的unix知识已经没法handle这个问题了,希望超能力者们能指点一二。

ArthurFyc 发表于 2022-4-1 01:03

就是运行一个后台程序?以我浅薄的linux知识来看这不就是 & 可以解决的么……还是我没理解你的需求

13号 发表于 2022-4-1 01:12

楼上+1.   虽然我也是bash菜鸡(一切bash能干的东西我都可以用ruby来干!),但是,在A里直接写 (B &) 这样不行吗?

纱夜抱着榴弹炮 发表于 2022-4-1 01:13

本质上是让 B 不再是 A 的子进程,nohup 或者 disown 应该都可以,不行的表现是什么?

Neozero 发表于 2022-4-1 01:53

Dreki 发表于 2022-4-1 01:56

看完你的描述我觉得nohup &显然是有用的,你是遇到了什么问题..?

我老婆呢 发表于 2022-4-1 10:40

tmux

tsubasa9 发表于 2022-4-1 10:58

左键点击会打开编辑是状态栏行为吗,如果是就是设计如此,不应该绕过

nessaj 发表于 2022-4-1 10:58

赤色彗星SEXY 发表于 2022-4-1 11:02

fork exec
用脚本就是 ( 你的脚本 &)

当然最好输入输出重定向一下

nohup和&一起用也是差不多的

yuandi42 发表于 2022-4-1 22:15

今天一大早傻逼老板突然叫我明天做汇报,忙着做ppt没看s1,抱歉抱歉。
我的需求其实是下面这个脚本,主要代码就一行,需求也很简单,检测trayer程序有没有跑,有就关掉,没有跑就打开。
用了nohup &,htop tree还是显示trayer是脚本的子进程。可以注意到dwmblocks那里有一行echo $(sb-tray), 换言之脚本运行还是卡在那里了,我再点击状态栏脚本也不会运行。我明白这时候我kill掉这个脚本之后trayer也会接着跑(这也是我理解的nohup的运行方式),但是我想要trayer独立于脚本之外运行,这样才能实现我想要的 点击打开-再点击关闭 的功能。https://s3.bmp.ovh/imgs/2022/04/01/cdaa55f6b45d455c.jpg
https://imgtu.com/i/q5YEGj

lvcha 发表于 2022-4-1 22:45

lvcha 发表于 2022-4-1 22:46

千羽宸 发表于 2022-4-1 23:40

yuandi42 发表于 2022-4-1 22:15
今天一大早傻逼老板突然叫我明天做汇报,忙着做ppt没看s1,抱歉抱歉。
我的需求其实是下面这个脚本,主要代 ...

Supervisor可以试试,

ipcjs 发表于 2022-4-2 05:18

bash居然可以写的这么复杂。。。

— from Google Pixel 6 Pro, Android 12 of S1 Next Goose v2.5.2-play

旧游时节 发表于 2022-4-2 07:35

你可以让systemd来管理这个进程,然后脚本里就只是发指令给systemd

emanon42 发表于 2022-4-2 08:05

这tilling wm配置有点审美的,礼貌求抄dotfile

yuandi42 发表于 2022-4-2 11:50

emanon42 发表于 2022-4-2 08:05
这tilling wm配置有点审美的,礼貌求抄dotfile

dotfiles
还有一部分配置在我自己的fork的dwm和dwmblocks里,现在还在折腾,不是完全体。

yuandi42 发表于 2022-4-2 23:47

可能我之前表述不是很清楚,我再解释一下我的需求吧。我希望脚本A启动命令(或脚本)B的时候,B就不是A的子进程。A不会因为B在持续运行而卡在B这一步。
在我的理解里,nohup &并不能满足我的需求,因为nohup能做到只是当A关闭的时候,让B忽略SIGHUP信号仍旧能够执行而已。
有版友建议我用systemd之类的,但这种实现方式我想我还是等到shell builtin 命令确定不能满足我的需求再试一试吧。一方面我不想为了这么一件很简单的事动用systemd这种大家伙,另外我也希望我写的脚本的依赖尽可能少一点。
P.S. 楼上还有人提到fork exec的,那个不是c里的东西吗,,,

maritimus 发表于 2022-4-3 00:39

yuandi42 发表于 2022-4-2 23:47
可能我之前表述不是很清楚,我再解释一下我的需求吧。我希望脚本A启动命令(或脚本)B的时候,B就不是A的子 ...

如果用A启动B,那B肯定是A的子进程。不然你觉得B的父进程应该是哪个?

shell我不太熟,不过我觉得 & 或者supervisor都能满足你的需求, &本身就是fork和exec

试了一下:

AlphardAlSheya 发表于 2022-4-3 00:50

不如直接 python multiprocessing,我觉得用 && 和 | 都解决不了的问题就不该用 shell script 了,可读性太寄吧差

—— 来自 Xiaomi MI 8, Android 10上的 S1Next-鹅版 v2.5.1

yuandi42 发表于 2022-4-3 02:11

maritimus 发表于 2022-4-3 00:39
如果用A启动B,那B肯定是A的子进程。不然你觉得B的父进程应该是哪个?

shell我不太熟,不过我觉得 & 或 ...

谢谢!我试着在terminal跑了一下nohup &, 似乎没有太大问题。那大概是dwmblocks的锅了,已经向上游提了个 issue. 如果shell script实现不了我就换成其他实现方式吧,,,

5long 发表于 2022-4-3 03:09

这种“如果一个进程还没启动过, 就启动, 否则就重启”的需求还是用专门的进程管理要简单些
你可能需要 systemd (user) unit
https://wiki.archlinux.org/title/Systemd/User
直接 `systemctl --user restart <service>` 就行了

赤色彗星SEXY 发表于 2022-4-3 10:58

估计是虚拟终端问题
setsid试试

赤色彗星SEXY 发表于 2022-4-3 12:17

想了下 应该是dwmblocks的退出代码里有主动结束子进程的行为

Linux实现方法是fork两次让孙进程挂到pid1上

最标准的做法还是让常驻进程让sysremd管理

nessaj 发表于 2022-4-3 12:38

abc12354a 发表于 2022-4-3 15:43

第一反应fork

—— 来自 samsung SM-G9750, Android 12上的 S1Next-鹅版 v2.5.2-play
页: [1]
查看完整版本: linux shell script 求解惑