一个定时让你起身活动的脚本

Submitted by Dot on Sun, 08/14/2016 - 11:13

自己总是在电脑前一坐半天乃至一天,不利于健康不说,长时间纠结某个问题往往事倍功半,所以就写了这么个脚本,初衷就是定时提醒自己起身放松一下。

这个脚本作用很简单,添加到crontab,0 8-19/1 * * * relax.sh,8至19点每小时整点运行。

脚本功能:

  • 在当前开启的所有虚拟终端(pts)上输出提示音,提示音频率由慢到快,最后用vlc播放音频文件“break.mp3”,并关闭屏幕;
  • 脚本运行期间(约43秒),任一新打开的虚拟终端都会输出,无法正常工作,强迫你停止;
  • 如果当前是16点,则用vlc播放眼保健操广播音eyes.f4v,这是我在网上找的老版本,80后的记忆;60s后关闭屏幕;
  • 因为脚本是向pts输出,所以只对linux桌面的虚拟终端用户有效,如gnome-terminal;tty用户需修改脚本;

 

未解决的问题: 

  • 音频文件“break.mp3”内容是一句“Let's take a break, see you later.”。原计划是用TTS(text to speeh),但是装了festival运行报错(fragmentation fault),应该是程序的问题。于是就找了个online tts,提供mp3下载,暂时先这么用;
  • vlc命令行指定音量的参数不知道是什么;
  • vlc播放完文件后进程一直在,不知道有没有自动关闭的参数;目前的解决办法是把vlc进程放到后台,sleep一段和音频长度相同的时间后kill $(pidof vlc)
  • 如果系统有其他声音正在输出,可能听不到音频。想法是将其它进程禁音,音频播放后再恢复。待实现;
  • 播放音频后面的重定向语句“< /dev/null &> /dev/null &”不能通过赋给变量来做替换,有别的办法么?

 

Aug 15, 2016 更新:

 

Aug 18, 2016 更新:

  • 加入自动关机,12点和19点开始5分钟倒计时,每分钟播报一次,最后10秒倒计时关机;
  • Fedora 24下,必须在cron中用sudo shutdown,即使有权限使用shutdown。因此需要在visudo中加入一条NOPASSWD:/user/sbin/shutdown
  • 更新代码;

 

Aug 19,2016更新:

  • 用mplayer代替vlc,自动关闭,且启动时可以指定音量;
  • 新增变量$play,取代之前的$vlcpara,通过判断mplayer是否安装以决定运行mplayer或vlc;
  • vlc并不需要“< /dev/null ”,但mplayer需要,否则无法后台运行,所以统一添加;
  • 让注释更好看;
  • 提交至github
  • 更新代码;

 

Aug 23, 2016更新:

  • abreak()里第一个for循环的表达式2,一直不明白为什么i>0&&j>0走到2.1就停了,甚至怀疑((...))里是否支持逻辑组合;最后发现,原来是一个逻辑错误,应该用||

完整代码如下:


#!/bin/bash
#
# dotr
#
# 0 8-19/1 * * * dotr
# A script for reminding you to AFK and have a little rest.
# Add to crontab so it will run per hour.

############### Variables ###############
hour=$(date +%H)
sdir=~/.local/sound
if [ -e /usr/bin/mplayer ]; then
	play="mplayer -quiet -volume 100"
else
	play="cvlc --quiet --play-and-exit"
fi

############### Functions ###############
# Get the list of /dev/pts/
function list(){
	l=$(ls /dev/pts | grep "[0-9]")
}

# Ask you to take a break.
function abreak(){
	# interval initialize to 2.5s, minus 0.1 every loop
	#for ((i=2,j=5;i>0||j>0;j--))
	for ((i=2,j=5;i+j>0;j--))
	do
		list
		for a in $l
		do
			echo -e "\a""\nLet's take a break, see you later." > /dev/pts/$a
		done
		sleep $i.$j

		if [ $j == 0 ]; then
			j=10
			i=$((i-1))
		fi

		# when interval reduces to 0.5s, do 20 times and exit
		if [ $i == 0 -a $j == 5 ]; then
			for ((k=20;k>0;k--))
			do
				list
				for a in $l
				do
					echo -e "\a""\nLet's take a break, see you later." > /dev/pts/$a
				done
				sleep $i.$j
			done
			#kill $(pidof vlc) &> /dev/null
			$play $sdir/break.mp3 < /dev/null &> /dev/null &
			sleep 2.5
			DISPLAY=:0 xset dpms force off
			#sleep 2.3
			#kill $(ps -C vlc | awk '/vlc/ {print $1}')
			#kill $(pidof vlc)
			exit
			#i=0;j=0
		fi
	done
}

# Do some exercise.
function eyes(){
	#kill $(pidof vlc) &> /dev/null
	$play $sdir/eyes.f4v < /dev/null &> /dev/null &
	sleep 60
	DISPLAY=:0 xset dpms force off
	#sleep 265
	#kill $(ps -C vlc | awk '/vlc/ {print $1}')
	#kill $(pidof vlc)
}

# Shutdown in 5 minutes.
function shutd () {
	# 5 minutes countdown.
	for i in $(ls $sdir | grep a.mp3 | sort -nr)
	do
		$play $sdir/$i < /dev/null &> /dev/null &
		if [ ${i:0:2} -eq "60" ]; then
			sleep 50
		else
			sleep 60
		fi
	done

	# 10 seconds countdown.
	for i in $(ls $sdir | grep b.mp3 | sort -nr)
	do
		$play $sdir/$i < /dev/null &> /dev/null
		sleep 0.1
	done

	if [ $hour -eq 12 ]; then
		$play $sdir/lunch.mp3 < /dev/null &> /dev/null
	else
		$play $sdir/night.mp3 < /dev/null &> /dev/null
	fi

	sudo shutdown now
}

############### Main Part ###############
if [[ $hour =~ ^1[29] ]] || [ "$1" == "s" ]; then
	shutd
elif [ $hour == 16 -o "$1" == "e" ]; then
	eyes
else
	abreak
fi


Tags

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.