我想从 bash 脚本调用对话框并返回值。我试过
set l = `xmessage -buttons Ok:0,"Not sure":1,Cancel:2 -default Ok -nearmouse "Is xmessage enough for the job ?" -timeout 10`
echo $l
对话框弹出,但无论我单击哪个按钮,echo $l 都会返回空白。
我想从 bash 脚本调用对话框并返回值。我试过
set l = `xmessage -buttons Ok:0,"Not sure":1,Cancel:2 -default Ok -nearmouse "Is xmessage enough for the job ?" -timeout 10`
echo $l
对话框弹出,但无论我单击哪个按钮,echo $l 都会返回空白。
我有以下两个简单的程序。
家长:
package main
import (
"fmt"
"syscall"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
Sys: &syscall.SysProcAttr{ // child in its own group
Setpgid: true,
Pgid: 0,
},
}
_, err := syscall.ForkExec("./child/child", []string{"child"}, attr)
if err != nil {
fmt.Println("Error:", err)
return
}
}
孩子:
package main
import (
"fmt"
"time"
)
func main() {
for {
fmt.Println("hi from child")
time.Sleep(time.Second * 5)
}
}
输出ps
:
yakog@yakog-computer:~/goprojects/parent$ ps -o pid,ppid,pgid,uid,wchan,stat,tt,command -t /dev/pts/19
PID PPID PGID UID WCHAN STAT TT COMMAND
1867701 1867320 1867701 1000 do_sel Ss+ pts/19 bash
1870508 2118 1870508 1000 ep_pol Sl pts/19 child
当我按下CTRL-Z
或 时CTRL-C
,它没有任何效果。这正是我所期望的,因为进程 1870508 不是前台作业的一部分,并且CTRL-Z
/CTRL-C
调用kill -SIGTSTP -1867701
/ kill -SIGINT -1867701
。因此,1870508 不会收到这些信号。
另外,当我调用kill -SIGINT 1870508
或 时kill -SIGSTOP 1870508
,进程被终止/暂停。我仍然可以理解。虽然 1870508 不是前台作业的一部分,但使用kill
命令我们“直接”将信号发送给进程。
但是,为什么不起作用kill -SIGTSTP 1870508
?启动./parent
进程并调用kill -SIGTSTP 1870508
命令后,实际上什么都没有发生(1870508 仍然具有状态R
/S
并继续打印到终端)。我不明白为什么它没有暂停进程(将其移动到)。它应该与和T
相同(我们“直接”向进程发送 -SIGTSTP),但是,在这种情况下它没有效果。-SIGINT
-SIGSTOP
奇怪的是,如果我们改变父代码(下面的代码)并使其在子进程创建后继续执行,那么它就kill -SIGTSTP 1870508
可以正常工作(子进程被暂停)。
package main
import (
"fmt"
"os/signal"
"syscall"
"time"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
Sys: &syscall.SysProcAttr{ // child in its own group
Setpgid: true,
Pgid: 0,
},
}
_, err := syscall.ForkExec("./child/child", []string{"child"}, attr)
signal.Ignore(syscall.SIGTSTP)
if err != nil {
fmt.Println("Error:", err)
return
}
for {
fmt.Println("hi from parent")
time.Sleep(time.Second * 7)
}
}
此外,当我调用kill -SIGSTOP 1870508
(将进程移动到T
状态)然后调用kill -SIGINT 1870508
它时,它不会终止进程......为什么?
我有一个 ssh .sh bash 脚本文件,我正在 cron 上运行它来检查网站状态。bash 脚本(运行时)引用本地 txt 文件,其中包含要检查的网站列表,它们是关闭还是启动。有时网站会关闭一段时间(维护等),我不想一遍又一遍地收到有关此特定停机时间的通知。所以我试图弄清楚如何在 txt 文件中注释掉此网站的行项目。每次我在 txt 文件中此网站地址的左侧添加 //、# 或 ## 时,它都不会跳过它。它仍然会检测行项目,并每十分钟向我的手机和电子邮件发送一次通知,告知我网站已关闭。这只是一个标准的 .sh 脚本和标准的 .txt 文件。只需要知道如何注释掉 txt 文件中的项目。(不是 bash 脚本)
这是.sh 文件:
#!/bin/bash
# Mailgun API configuration
MAILGUN_API_KEY="redacted"
MAILGUN_DOMAIN="redacted"
TO_EMAIL="redacted"
FROM_EMAIL="redacted"
cd /redacted/redacted/uptime
# File containing website URLs
WEBSITE_FILE="premium-websites.txt"
while IFS= read -r website; do
response=$(curl -Is --max-time 10 "$website" | head -n 1)
response_code=$(echo "$response" | awk '{print $2}')
if [[ "$response_code" != "200" ]]; then
if [[ "$response_code" == "" ]]; then
# Website timed out, send email notification
subject="Website Timeout: $website"
body="The Premium Care website $website timed out. Please investigate. Sent from corp"
elif [[ "$response_code" == "500" ]]; then
# Website has a 500 error, send email notification
subject="Website 500 Error: $website"
body="The Premium Care $website returns a 500 Internal Server Error. Please investigate. Sent from corp"
else
# Website is down, send email notification
subject="Website Down: $website"
body="The Premium Care website $website is down. Please investigate. Sent from corp"
fi
curl -s --user "api:$MAILGUN_API_KEY" \
https://api.mailgun.net/v3/$MAILGUN_DOMAIN/messages \
-F from="$FROM_EMAIL" \
-F to="$TO_EMAIL" \
-F subject="$subject" \
-F text="$body"
echo "[$(date)] $website issue detected. Email notification sent."
else
echo "[$(date)] $website is up."
fi
done < "$WEBSITE_FILE"
在此处输入代码 在此处输入代码
这是文本文件(仅为示例):
https://websites1.com
https://websites2.com
https://websites3.com
我昨天晚上(德国时间周日午夜之前)做了以下事情:
今天的日期
$ LC_TIME="en.GB.UTF8" date --iso-8601
2025-01-12
$ LC_TIME="en.GB.UTF8" date +%u
7
$ LC_TIME="en.GB.UTF8" date +%a
Sun
$ LC_TIME="en_GB.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
$ LC_TIME="en_IE.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
$ LC_TIME="en_IN.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
$ LC_TIME="en_US.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
$ LC_TIME="en_DE.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
$ LC_TIME="en_JP.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
$ LC_TIME="en_DK.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
$ LC_TIME="en_CA.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
$ LC_TIME="en_AU.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
我今天(2025-01-13)做了这件事(在德国)
$ LC_TIME="en_AU.UTF-8" date -d "this-week-sunday" --iso-8601
2025-01-19
$ LC_TIME="en_AU.UTF-8" date -d "last-week-sunday" --iso-8601
2025-01-12
$ LC_TIME="en_AU.UTF-8" date -d "next-week-sunday" --iso-8601
2025-01-26
因此,今天它似乎给出了部分正确的结果。今天的输出有什么问题:如果昨天的输出this-week-monday
是2025-01-13
这样的,计算机不知何故在每个地区都将星期日算作一周的第一天(我上面显示的)。所以"this-week-sunday"
应该是昨天而不是 2025-01-19(如今天所示)。
昨天
$ LC_TIME="en_GB.UTF-8" date -d "this-week-monday" --iso-8601
2025-01-13
今天
env -i bash --norc --noprofile
bash-5.2$ LC_TIME="en_AU.UTF-8" date -d "this-week-sunday" --iso-8601
2025-01-19
问题:如果昨天(2025-01-12,星期日)this-week-monday
是 13 号,那么今天this-week-sunday
应该是昨天而不是2025-01-19
为什么我得到错误的日期输出?
我开始学习 Linux tty 和信号并遇到了一些麻烦。
我正在阅读并使用《TTY 揭秘》作为参考。
我做了两个简单的golang程序。
家长:
package main
import (
"fmt"
"syscall"
"time"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
}
_, err := syscall.ForkExec("./child/child", []string{"child"}, attr)
if err != nil {
fmt.Println("Error:", err)
return
}
for {
fmt.Println("hi from parent")
time.Sleep(time.Second * 10)
}
}
孩子:
package main
import (
"fmt"
"os/signal"
"syscall"
"time"
)
func main() {
signal.Ignore(syscall.SIGTSTP) // golang's way to handle (ignore) signal
for {
fmt.Println("hi from child")
time.Sleep(time.Second * 5)
}
}
它们非常简单。两者都只是每 5/10 秒向 tty 打印一条消息。唯一的区别是子进程忽略了 SIGTSTP(ctrl-z)信号。因此,当我按下 ctrl-z 时,它会暂停父进程,而不会暂停子进程。这正是我所期望的。然而,我没有想到的是,整个组从前台移到了后台组。它与TTY 揭秘形成对比。具体来说:
当前台作业中的所有进程都已暂停时,会话领导者将从 TTY 设备读取当前配置,并将其存储起来以供以后检索。会话领导者继续使用 ioctl 调用将自己安装为 TTY 的当前前台进程组。然后,它会打印类似“[1]+ Stopped”的内容来通知用户作业刚刚被暂停。
它表示仅当前台作业中的所有进程都已暂停时,会话领导者(shell / bash)才会将该组移至后台作业......
ps l -t /dev/pts/0
ctrl-z 前后的结果:
yakog@yakog-computer:~/goprojects/parent$ ps l -t /dev/pts/0
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 1000 1747467 1747441 20 0 14288 5632 do_wai Ss pts/0 0:00 bash
0 1000 1747496 1747467 20 0 1225432 1792 ep_pol Sl+ pts/0 0:00 ./parent
0 1000 1747501 1747496 20 0 1225424 1664 ep_pol Sl+ pts/0 0:00 child
yakog@yakog-computer:~/goprojects/parent$ ps l -t /dev/pts/0
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 1000 1747467 1747441 20 0 14288 5632 do_sel Ss+ pts/0 0:00 bash
0 1000 1747496 1747467 20 0 1225432 1792 do_sig Tl pts/0 0:00 ./parent
0 1000 1747501 1747496 20 0 1225680 1792 ep_pol Sl pts/0 0:00 child
如果我将忽略 ( signal.Ignore(syscall.SIGTSTP)
) 从子进程移至父进程,则一切正常(从我的角度来看)。子进程暂停 (T),父进程正常恢复 (R/S),但该组仍是前台作业。
yakog@yakog-computer:~/goprojects/parent$ ps l -t /dev/pts/0
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 1000 1749437 1749410 20 0 14420 5632 do_wai Ss pts/0 0:00 bash
0 1000 1749957 1749437 20 0 1225448 1920 ep_pol Sl+ pts/0 0:00 ./parent
0 1000 1749962 1749957 20 0 1225412 1664 ep_pol Sl+ pts/0 0:00 child
yakog@yakog-computer:~/goprojects/parent$ ps l -t /dev/pts/0
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 1000 1749437 1749410 20 0 14420 5632 do_wai Ss pts/0 0:00 bash
0 1000 1749957 1749437 20 0 1225448 1920 ep_pol Sl+ pts/0 0:00 ./parent
0 1000 1749962 1749957 20 0 1225668 1792 do_sig Tl+ pts/0 0:00 child
为什么会发生这种情况,我忽略了什么?
使用命令时echo $100
,我得到了输出 00,而如果我给出echo $d00
命令,它会给出一个空行!为什么?bash 内部是否有方法可以对两者进行不同的解释?
在 Kubuntu Linux 上,Google Chrome 浏览器会为文件添加校验和,以防止手动编辑文件。所以我正在编写一个脚本来添加校验和。
$ cat .config/google-chrome/Default/Custom\ Dictionary.txt
AATEST
dotancohen
checksum_v1 = 2b7288da7c9556608de620e65308efa4$
没问题,我将复制整个文件(不包括最后一行)并检查其 MD5 哈希值是否与校验和匹配。
$ head -n -1 .config/google-chrome/Default/Custom\ Dictionary.txt > ~/chrome-dict
$ cat ~/chrome-dict
AATEST
dotancohen
$ md5sum ~/chrome-dict
2b7288da7c9556608de620e65308efa4 /home/dotancohen/chrome-dict
正如预期的那样,我们得到了2b7288da7c9556608de620e65308efa4
。它匹配!因此,让我们将其添加到文件末尾。
$ { printf "checksum_v1 = " ; printf $(md5sum -z ~/chrome-dict | awk '{print $1}') ; } >> ~/chrome-dict
$ cat ~/chrome-dict
AATEST
dotancohen
checksum_v1 = 08f7dd79a17e12b178a1010057ef5e34$
不,校验和错误!让我们尝试 cat 以确保两个语句之间没有任何内容写入文件printf
。
$ head -n -1 .config/google-chrome/Default/Custom\ Dictionary.txt > ~/chrome-dict
$ cat ~/chrome-dict
AATEST
dotancohen
$ { printf "checksum_v1 = " ; printf $(md5sum -z ~/chrome-dict | awk '{print $1}') ; } | cat >> ~/chrome-dict
$ cat ~/chrome-dict
AATEST
dotancohen
checksum_v1 = 08f7dd79a17e12b178a1010057ef5e34$
校验和仍然错误!我们来试试 tmp 文件。
$ head -n -1 .config/google-chrome/Default/Custom\ Dictionary.txt > ~/chrome-dict
$ cat ~/chrome-dict
AATEST
dotancohen
$ { printf "checksum_v1 = " ; printf $(md5sum -z ~/chrome-dict | awk '{print $1}') ; } >> ~/chrome-dict-tmp
$ cat ~/chrome-dict-tmp >> ~/chrome-dict && rm ~/chrome-dict-tmp
$ cat ~/chrome-dict
AATEST
dotancohen
checksum_v1 = 2b7288da7c9556608de620e65308efa4$
成功了!为什么将输出重定向到文件末尾的一行代码没有~/chrome-dict
返回正确的 MD5 哈希值?
我需要按顺序运行多个 shell 脚本 (s1.sh、s2.sh、s3.sh),要求如下:
现状:
工作流程示例:
我正在考虑的潜在方法:我正在考虑将 stdout 和 stderr 重定向到一个文件,并每秒检查一次该文件的修改时间。如果该文件 1 分钟内没有被写入,我可以假设脚本没有输出并终止它。但是,我不确定这种方法是否可行,或者是否有更好的解决方案。
有人实现过类似的东西吗?谢谢。
我有一个 bash 脚本,它使用 打开一个窗口notify-send
。我想在脚本结束时关闭该窗口,但我找不到任何东西kill
。
该问题与https://askubuntu.com/questions/639754/is-it-possible-to-cancel-or-clear-a-notification-created-by-using-notify-send重复,但对我而言,这些答案都不起作用。公认的答案是终止一个名为 的进程notify-osd
,但我没有类似的东西。值得注意的是,这个问题已有十年历史了。
我的脚本就像
notify-send -u critical -i ~/.icons/my-icon.png "$titletext" "$helptext"
helppid=$!
…
kill $helppid
(紧急程度设置至关重要,以便帮助窗口保持打开状态直到明确关闭。)
问题是$!
没有返回值。ps -ef | grep -i notify
显示没有与我的脚本相关的任何内容。
我找到了一种解决方法,使用print-id
以下功能( https://askubuntu.com/a/161852notify-send
中描述):
print-id=$(notify-send -p -u critical -i ~/.icons/my-icon.png "$titletext" "$helptext")
notify-send -r $print-id -u low ~/.icons/my-icon.png "$titletext" Finished
有人能描述一种更好的方法来关闭帮助对话框吗?我已经阅读了 的建议yad
,不知道是否要安装并评估它。
关于 bash 监听/等待我的命令时终端所处的模式,我有三个小问题:
stty -echo
在之后额外调用stty -icanon
?换句话说,终端是否可以处于非规范模式并由驱动程序“自动”回显,这两件事(非规范模式和“自动”回显)不是互相排斥的?