View previous topic :: View next topic |
Author |
Message |
jpsollie Guru
Joined: 17 Aug 2013 Posts: 323
|
Posted: Tue Apr 18, 2023 6:41 am Post subject: feature request: update hd-idle |
|
|
The hd-idle program in the portage tree is quite outdated these days,
where should I put a feature request to build it from a more "modern" source?
I myself tried the one of adelolmo on github (https://github.com/adelolmo/hd-idle.git), and got a few nice config files for openrc:
Code: |
#!/sbin/openrc-run
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
description="Utility for spinning down hard disks after a period of idle time"
command="/usr/local/sbin/hd-idle"
command_args="${HD_IDLE_OPTS}"
depend() {
after bootmisc
}
start() {
disks="-i $HD_IDLE_DEFAULT_TIMEOUT -c $HD_IDLE_DEFAULT_PROTO ";
[ -z "$HD_IDLE_EXCLUSIONS" ] || disks+=$(lsscsi | grep -E "(${HD_IDLE_EXCLUSIONS//\ /\)\(})" | sed 's/.*\/dev\/\(sd.*\)$/-a \1 -i 0 /g') ;
[ -z "$HD_IDLE_SCSI_TIMEOUT" ] || disks+=$(lsscsi | grep -v -E "(${HD_IDLE_EXCLUSIONS//\ /\)\(})" | grep -v ATA | grep disk | grep -v nvme | sed "s/.*\/dev\/\(sd.*\)$/-a \1 -i ${HD_IDLE_SCSI_TIMEOUT} -c scsi -p 3/g") ;
[ -z "$HD_IDLE_ATA_TIMEOUT" ] || disks+=$(lsscsi | grep -v -E "(${HD_IDLE_EXCLUSIONS//\ /\)\(})" | grep ATA | grep disk | grep -v nvme | sed "s/.*\/dev\/\(sd.*\)$/-a \1 -i ${HD_IDLE_ATA_TIMEOUT} -c ata -p 0 /g") ;
HD_IDLE_OPTS="${disks} -l ${HD_LOG_OPTS}"
start-stop-daemon --start --quiet --oknodo --background --exec $command -- $HD_IDLE_OPTS
}
|
Code: |
#is default protocol sata or scsi?
HD_IDLE_DEFAULT_PROTO="ata"
#timeout (in seconds) for entering powersave of default disks. 0 means do not spin down
HD_IDLE_DEFAULT_TIMEOUT="300"
#timeout (in seconds) for entering powersave of SATA disks. 0 means do not spin down, if default is ata then this value must be empty
HD_IDLE_ATA_TIMEOUT=""
#timeout (in seconds) for entering powersave of SCSI disks. 0 means do not spin down, if default is scsi then this value must be empty
HD_IDLE_SCSI_TIMEOUT="300"
#logfile to write events to
HD_LOG_OPTS="/var/log/hd-idle.log"
#disks which should be omitted from entering powersave. Model or /dev/sd* are supported, separated by space
HD_IDLE_EXCLUSIONS="ST1000"
|
_________________ The power of Gentoo optimization (not overclocked): [img]https://www.passmark.com/baselines/V10/images/503714802842.png[/img] |
|
Back to top |
|
|
Banana Moderator
Joined: 21 May 2004 Posts: 1747 Location: Germany
|
|
Back to top |
|
|
Hu Administrator
Joined: 06 Mar 2007 Posts: 22694
|
Posted: Tue Apr 18, 2023 5:27 pm Post subject: |
|
|
If you find yourself using both grep and sed together, or multiple chained greps, there is usually an easier way to process the text to get the result you want. Similarly, running lsscsi three times looks questionable. |
|
Back to top |
|
|
jpsollie Guru
Joined: 17 Aug 2013 Posts: 323
|
Posted: Mon Apr 24, 2023 11:41 am Post subject: |
|
|
Hu wrote: | If you find yourself using both grep and sed together, or multiple chained greps, there is usually an easier way to process the text to get the result you want. Similarly, running lsscsi three times looks questionable. |
Yes, absolutely. I should consider using lsblk as well to use the info the kernel already has.
However: how would you improve the chained grep problem then? Request sed to drop lines not relevant? or any better option which may be more failsafe?
*EDIT* if you have a suggestion for a more "clean" way of working aside from "try device name or part of model number", it would greatly be appreciated _________________ The power of Gentoo optimization (not overclocked): [img]https://www.passmark.com/baselines/V10/images/503714802842.png[/img] |
|
Back to top |
|
|
Hu Administrator
Joined: 06 Mar 2007 Posts: 22694
|
Posted: Mon Apr 24, 2023 3:56 pm Post subject: |
|
|
Yes, tell sed to delete the lines. To more fully answer your question with a rewrite requires more time than I can spare today. However, I observe that in this case all three pipelines add to the same shell variable, albeit under different guards. This suggests you could have one more complex pipeline that adds to the shell variable once, which would avoid the need for multiple lsscsi calls and possibly even avoid saving its output to a temporary file. |
|
Back to top |
|
|
jpsollie Guru
Joined: 17 Aug 2013 Posts: 323
|
Posted: Fri Aug 09, 2024 9:51 am Post subject: |
|
|
hi everyone,
sorry for reviving this old thread, but I think I got what Hu wanted:
Code: |
disks="-i $HD_IDLE_DEFAULT_TIMEOUT -c $HD_IDLE_DEFAULT_PROTO ";
#trim the exclusions list
HD_IDLE_EXCLUSIONS="${HD_IDLE_EXCLUSIONS#\ }"
HD_IDLE_EXCLUSIONS="${HD_IDLE_EXCLUSIONS%\ }"
#only consider sata and sas drives, so blacklist usb
HD_IDLE_EXCLUSIONS+=" usb"
ignoring_disks=$(lsblk -S -o name,vendor,model,tran | grep -E "(${HD_IDLE_EXCLUSIONS// /\)|\(})")
working_disks=$(lsblk -S -o name,vendor,model,tran | grep -v -E "(${HD_IDLE_EXCLUSIONS// /\)|\(})")
[[ -z "ignoring_disks" ]] || disks+=$(echo "$ignoring_disks" | sed 's/^\(sd[a-z]*\)[\t\ ].*$/-a \1 -i 0 /g') ;
[[ -z "$HD_IDLE_ATA_TIMEOUT" ]] || disks+=$(echo "$working_disks" | sed -n "s/^\(sd[a-z]\+\)[\ \t]\+ATA.*/-a \1 -i ${HD_IDLE_ATA_TIMEOUT} -c ata -p 0 /p") ;
[[ -z "$HD_IDLE_SCSI_TIMEOUT" ]] || disks+=$(echo "$working_disks" | sed -n "s/^\(sd[a-z]\+\)[\ \t]\+[^\t^\ ^A^T]\{1,3\}.*/-a \1 -i ${HD_IDLE_SCSI_TIMEOUT} -c scsi -p 3 /p") ;
HD_IDLE_OPTS="${disks} -l ${HD_LOG_OPTS}"
start-stop-daemon --start --background -1 ${HD_LOG_OPTS} -2 ${HD_LOG_OPTS} --exec $command -- $HD_IDLE_OPTS
|
@Hu: what do you think of this way-of-working?
*EDIT*: corrected typo in code _________________ The power of Gentoo optimization (not overclocked): [img]https://www.passmark.com/baselines/V10/images/503714802842.png[/img] |
|
Back to top |
|
|
Hu Administrator
Joined: 06 Mar 2007 Posts: 22694
|
Posted: Fri Aug 09, 2024 2:23 pm Post subject: |
|
|
It is better, but you are still running list commands repeatedly. jpsollie wrote: | Code: | ignoring_disks=$(lsblk -S -o name,vendor,model,tran | grep -E "(${HD_IDLE_EXCLUSIONS// /\)|\(})")
working_disks=$(lsblk -S -o name,vendor,model,tran | grep -v -E "(${HD_IDLE_EXCLUSIONS// /\)|\(})") |
| This is two invocations of lsblk with the same arguments. Using a temporary file, or some cleverness with tee and pipes, could cut it down to one. You could add -n to suppress the header line, which may simplify later logic.
Considering the simple and line-oriented nature of the output, you could even capture the whole lsblk into a shell variable, and filter it later. Code: | lsblk -n -S -o name,vendor,model,tran | { while read -r found_disk; do
# found_disk is now one line of output from lsblk. Break it into
# pieces, and decide whether to consider the drive ignored or
# working.
FIXME - not implemented yet
done; } | I started this post intending to write the body of that while loop for you, but I again find myself without time to finish it. Sorry. If you want to pursue that route, post back and I can try to look at it later.
If you decide to try to write that for yourself, note that I put braces around the loop intentionally. When you pass the close brace, any variables created in that pipeline will be inaccessible, so you need to move all later logic that depends on the lsblk output (which appears to be everything) to occur after the done and before the ; }. For example: Code: |
lsblk $args | while read -r a; do var+="$a"; done
echo "$var" # result of while loop may be lost!
lsblk $args | { while read -r a; do var+="$a"; done; echo "$var"; } # OK, changes from loop are still visible | This is because the shell will (usually) run the right hand side of the pipe in a forked process, so when the statement ends, changes to its variables are lost. The braces give you a compound statement, so you can access variables after the loop but before you exit the forked process. jpsollie wrote: | Code: | [[ -z "ignoring_disks" ]] || disks+=$(echo "$ignoring_disks" | sed 's/^\(sd[a-z]*\)[\t\ ].*$/-a \1 -i 0 /g') ; |
| This will not do what you want, since you test whether the literal string ignoring_disks is empty, and it never is. I think you meant to test whether the value of the variable ignoring_disks is empty. jpsollie wrote: | Code: | [[ -z "$HD_IDLE_ATA_TIMEOUT" ]] || disks+=$(echo "$working_disks" | sed -n "s/^\(sd[a-z]\+\)[\ \t]\+ATA.*/-a \1 -i ${HD_IDLE_ATA_TIMEOUT} -c ata -p 0 /p") ;
[[ -z "$HD_IDLE_SCSI_TIMEOUT" ]] || disks+=$(echo "$working_disks" | sed -n "s/^\(sd[a-z]\+\)[\ \t]\+[^\t^\ ^A^T]\{1,3\}.*/-a \1 -i ${HD_IDLE_SCSI_TIMEOUT} -c scsi -p 3 /p") ; |
| These could be combined, by building up the arguments to sed and then running one sed with both expressions. |
|
Back to top |
|
|
jpsollie Guru
Joined: 17 Aug 2013 Posts: 323
|
Posted: Sat Aug 10, 2024 6:29 pm Post subject: |
|
|
Hu wrote: | It is better, but you are still running list commands repeatedly. jpsollie wrote: | Code: | ignoring_disks=$(lsblk -S -o name,vendor,model,tran | grep -E "(${HD_IDLE_EXCLUSIONS// /\)|\(})")
working_disks=$(lsblk -S -o name,vendor,model,tran | grep -v -E "(${HD_IDLE_EXCLUSIONS// /\)|\(})") |
| This is two invocations of lsblk with the same arguments. Using a temporary file, or some cleverness with tee and pipes, could cut it down to one. You could add -n to suppress the header line, which may simplify later logic.
Considering the simple and line-oriented nature of the output, you could even capture the whole lsblk into a shell variable, and filter it later. Code: | lsblk -n -S -o name,vendor,model,tran | { while read -r found_disk; do
# found_disk is now one line of output from lsblk. Break it into
# pieces, and decide whether to consider the drive ignored or
# working.
FIXME - not implemented yet
done; } | I started this post intending to write the body of that while loop for you, but I again find myself without time to finish it. Sorry. If you want to pursue that route, post back and I can try to look at it later.
|
Yes, the idea of switching to lsblk was because it extracts from linux' block system instead of querying hw, like lsscsi does.
As linux already keeps it, the overhead will be insignificant, right? So I thought wasting an extra variabele on it wouldn't be useful.
Quote: |
If you decide to try to write that for yourself, note that I put braces around the loop intentionally. When you pass the close brace, any variables created in that pipeline will be inaccessible, so you need to move all later logic that depends on the lsblk output (which appears to be everything) to occur after the done and before the ; }. For example: Code: |
lsblk $args | while read -r a; do var+="$a"; done
echo "$var" # result of while loop may be lost!
lsblk $args | { while read -r a; do var+="$a"; done; echo "$var"; } # OK, changes from loop are still visible | This is because the shell will (usually) run the right hand side of the pipe in a forked process, so when the statement ends, changes to its variables are lost. The braces give you a compound statement, so you can access variables after the loop but before you exit the forked process.
|
Wouldn't it cause a lot more overhead to use a loop instead of piping everything, like I'm doing now?
Quote: | jpsollie wrote: | Code: | [[ -z "ignoring_disks" ]] || disks+=$(echo "$ignoring_disks" | sed 's/^\(sd[a-z]*\)[\t\ ].*$/-a \1 -i 0 /g') ; |
| This will not do what you want, since you test whether the literal string ignoring_disks is empty, and it never is. I think you meant to test whether the value of the variable ignoring_disks is empty. |
Yes, absolutely. Sorry, forgot about that Quote: | jpsollie wrote: | Code: | [[ -z "$HD_IDLE_ATA_TIMEOUT" ]] || disks+=$(echo "$working_disks" | sed -n "s/^\(sd[a-z]\+\)[\ \t]\+ATA.*/-a \1 -i ${HD_IDLE_ATA_TIMEOUT} -c ata -p 0 /p") ;
[[ -z "$HD_IDLE_SCSI_TIMEOUT" ]] || disks+=$(echo "$working_disks" | sed -n "s/^\(sd[a-z]\+\)[\ \t]\+[^\t^\ ^A^T]\{1,3\}.*/-a \1 -i ${HD_IDLE_SCSI_TIMEOUT} -c scsi -p 3 /p") ; |
| These could be combined, by building up the arguments to sed and then running one sed with both expressions. | ouch ... That sounds like a hard regex, far beyond my knowledge _________________ The power of Gentoo optimization (not overclocked): [img]https://www.passmark.com/baselines/V10/images/503714802842.png[/img] |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|