RRDTool GPRINT formatting with printf - linux

Closely related to this question: Bash printf prefix
I have the following Bash script that is generating an RRDGraph with RRDTool.
#!/bin/bash
now=$(date +%s)
now_formatted=$(date +%s | awk '{printf "%s\n", strftime("%c",$1)}' | sed -e 's/:/\\:/g')
# create power graph for last week
/usr/bin/rrdtool graph /var/www/power-week.png \
--start end-7d --width 543 --height 267 --end $now-1min --slope-mode \
--vertical-label "Watts" --lower-limit 0 \
--alt-autoscale-max \
--title "Power: Last week vs. week before" \
--watermark "(©) $(date +%Y) Alyn R. Tiedtke" \
--font WATERMARK:8 \
DEF:Power=/root/currentcost/ccdata.rrd:Power:AVERAGE \
DEF:Power2=/root/currentcost/ccdata.rrd:Power:AVERAGE:end=$now-7d1min:start=end-7d \
VDEF:Last=Power,LAST \
VDEF:First=Power,FIRST \
VDEF:Min=Power,MINIMUM \
VDEF:Peak=Power,MAXIMUM \
VDEF:Average=Power,AVERAGE \
CDEF:kWh=Power,1000,/,168,* \
CDEF:Cost=kWh,.1029,* \
SHIFT:Power2:604800 \
LINE1:Power2#00CF00FF:"Last Week\\n" \
HRULE:Min#58FAF4:"Min " \
GPRINT:Power:MIN:"%6.2lf%sW" \
COMMENT:"\\n" \
LINE1:Power#005199FF:"Power " \
AREA:Power#00519933:"" \
GPRINT:Last:"%6.2lf%sW" \
COMMENT:"\\n" \
HRULE:Average#9595FF:"Average" \
GPRINT:Power:AVERAGE:"%6.2lf%sW" \
COMMENT:"\\n" \
HRULE:Peak#ff0000:"Peak " \
GPRINT:Power:MAX:"%6.2lf%sW" \
COMMENT:"\\n" \
GPRINT:kWh:AVERAGE:" total %6.2lfkWh\\n" \
GPRINT:Cost:AVERAGE:" cost %6.2lf £\\n" \
GPRINT:Cost:AVERAGE:"$(printf \\" cost %11s\\" £%.2lf | sed 's/\£/\£ /g')\\n" \
COMMENT:" \\n" \
GPRINT:First:"Showing from %c\\n":strftime \
GPRINT:Last:" to %c\\n":strftime \
COMMENT:" Created at $now_formatted"
Which produces a graph like this (notice the leading \ on the lower cost line in the legend):-
Concentrating specifically on the following line:-
GPRINT:Cost:AVERAGE:"$(printf \\" cost %11s\\" £%.2lf | sed 's/\£/\£ /g')\\n" \
This is the line that is printing out the lower cost line in the legend.
I am passing a GPRINT formatted value of £4.54 to Bash's printf function to be padded out to 11 spaces and a cost label prefixed on it. I am then piping this to sed to add a space between the £ and the actual value.
What I want to know is, why is the escaped \ coming through in the output? If I remove the \\ just after printf bash complains that something is missing.
How would I suppress this \ from coming through in the output.

Try this line:
GPRINT:Cost:AVERAGE:"$(printf ' cost %11s' £%.2lf | sed 's/\£/\£ /g')\\n" \
I changed the inner " marks to ' marks and removed the backslashes.

Related

cat EOF keeps indenting and interprets variables

use 'EOF',it can keep indenting, but it can't explain variables
[root#master ~]# registry=10.105.100.4/library
[root#master ~]# cat > /etc/sysconfig/kubelet << 'EOF'
> KUBELET_EXTRA_ARGS=--pod-infra-container-image=${registry}/pause:3.1 \
> --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice \
> --feature-gates=LocalStorageCapacityIsolation=true \
> --kube-reserved-cgroup=/kubepods.slice --kube-reserved=cpu=500m,memory=500Mi,ephemeral-storage=1Gi \
> --system-reserved-cgroup=/system.slice --system-reserved=cpu=500m,memory=500Mi,ephemeral-storage=1Gi \
> --eviction-hard=memory.available<500Mi,nodefs.available<10% \
> --max-pods=250
> EOF
[root#master ~]# cat /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS=--pod-infra-container-image=${registry}/pause:3.1 \
--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice \
--feature-gates=LocalStorageCapacityIsolation=true \
--kube-reserved-cgroup=/kubepods.slice --kube-reserved=cpu=500m,memory=500Mi,ephemeral-storage=1Gi \
--system-reserved-cgroup=/system.slice --system-reserved=cpu=500m,memory=500Mi,ephemeral-storage=1Gi \
--eviction-hard=memory.available<500Mi,nodefs.available<10% \
--max-pods=250
just use EOF,It can interpret variables, but it can't keep indenting,
[root#master ~]# registry=10.105.100.4/library
[root#master ~]# cat > /etc/sysconfig/kubelet << EOF
> KUBELET_EXTRA_ARGS=--pod-infra-container-image=${registry}/pause:3.1 \
> --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice \
> --feature-gates=LocalStorageCapacityIsolation=true \
> --kube-reserved-cgroup=/kubepods.slice --kube-reserved=cpu=500m,memory=500Mi,ephemeral-storage=1Gi \
> --system-reserved-cgroup=/system.slice --system-reserved=cpu=500m,memory=500Mi,ephemeral-storage=1Gi \
> --eviction-hard=memory.available<500Mi,nodefs.available<10% \
> --max-pods=250
> EOF
[root#master ~]# cat /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS=--pod-infra-container-image=10.105.100.4/library/pause:3.1 --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice --feature-gates=LocalStorageCapacityIsolation=true --kube-reserved-cgroup=/kubepods.slice --kube-reserved=cpu=500m,memory=500Mi,ephemeral-storage=1Gi --system-reserved-cgroup=/system.slice --system-reserved=cpu=500m,memory=500Mi,ephemeral-storage=1Gi --eviction-hard=memory.available<500Mi,nodefs.available<10% --max-pods=250
[root#master ~]#
Is there any way for both to take effect at the same time?
You have to escape the backslashes at the end of the lines (Tested with bash and zsh; I assume other shells are similar):
$ cat > foo.txt <<EOF
line 1 \\
line 2
EOF
$ cat foo.txt
line 1 \
line 2

improve the performance of making slide video using ffmpeg

I have 10 images(1080x1920) and 2 video(1080x1920).
I want to merge all of them to make a final video using command:
INPUT_DATA=(_img1.jpg vid1.mp4 _img2.jpg vid2.mp4 _img3.jpg _img4.jpg _img5.jpg _img6.jpg _img7.jpg _img8.jpg _img9.jpg _img10.jpg)
IMAGE_TIME_SPAN=5
INPUT_DIR="input"
OUTPUT_DIR="output"
BACKGROUND_MUSIC="$INPUT_DIR/background.mp3"
OUTPUT_STEP1="$OUTPUT_DIR/tmp_video.mp4"
OUTPUT_STEP3="$OUTPUT_DIR/tmp_background.mp3"
OUTPUT_FILE="$OUTPUT_DIR/final.mp4"
SCALE_SIZE="1080x1920"
ffmpeg -y \
-f lavfi -t 1 -i anullsrc \
-i $INPUT_DIR/${INPUT_DATA[0]} \
-i $INPUT_DIR/${INPUT_DATA[1]} \
-i $INPUT_DIR/${INPUT_DATA[2]} \
-i $INPUT_DIR/${INPUT_DATA[3]} \
-i $INPUT_DIR/${INPUT_DATA[4]} \
-i $INPUT_DIR/${INPUT_DATA[5]} \
-i $INPUT_DIR/${INPUT_DATA[6]} \
-i $INPUT_DIR/${INPUT_DATA[7]} \
-i $INPUT_DIR/${INPUT_DATA[8]} \
-i $INPUT_DIR/${INPUT_DATA[9]} \
-i $INPUT_DIR/${INPUT_DATA[10]} \
-i $INPUT_DIR/${INPUT_DATA[11]} \
-filter_complex \
"[1:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img1]; \
[2:v]fade=t=in:st=0:d=4:alpha=1,scale=$SCALE_SIZE[v1]; \
[3:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img2]; \
[4:v]fade=t=in:st=0:d=4:alpha=1,scale=$SCALE_SIZE[v2]; \
[5:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img3]; \
[6:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img4]; \
[7:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img5]; \
[8:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img6]; \
[9:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img7]; \
[10:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img8]; \
[11:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img9]; \
[12:v]fade=t=in:st=0:d=4:alpha=1,zoompan=z='zoom+0.0009':d=25*$IMAGE_TIME_SPAN:s=$SCALE_SIZE[img10]; \
[img1][0:a][v1][0:a][img2][0:a][v2][0:a][img3][0:a][img4][0:a][img5][0:a][img6][0:a][img7][0:a][img8][0:a][img9][0:a][img10][0:a]concat=n=12:v=1:a=1" \
-pix_fmt yuv420p -c:v libx264 \
$OUTPUT_STEP1
I run this command on a virtual machine (Linux, 4GB memories) and it takes ~11 min to finish! It takes too long and I want to reduce the process time to less than 5 min.
Any suggestion for the better performance.

Import file to script and fill variables inside the file

I have script import.sh
. properties
sql=$(cat sql.sql)
${psql_path}/psql \
-X \
--set ON_ERROR_STOP=on \
--set AUTOCOMMIT=on \
--echo-all \
${sql}
${dbname} > ${log_file} 2>> ${log_file}
and file properties
psql_path="/usr/pgsql-9.6/bin"
dbname="postgres"
path="/opt/files"
log_file="ok.log"
and file sql.sql
-c "truncate table SCHEMA.TABLE1;" \
-c "\\copy SCHEMA.TABLE1 FROM '${path}/TABLE1.tsv' DELIMITER ';' CSV HEADER ENCODING 'UTF8' QUOTE '\"'" \
-c "truncate table SCHEMA.TABLE2;" \
-c "\\copy SCHEMA.TABLE1 FROM '${path}/TABLE2.tsv' DELIMITER ';' CSV HEADER ENCODING 'UTF8' QUOTE '\"'" \
i need to run psql command with importing lines from file sql.sql on the line ${sql} in script import.sh but including text /opt/files instead of the variable itself ${path}, eg:
${psql_path}/psql \
-X \
--set ON_ERROR_STOP=on \
--set AUTOCOMMIT=on \
--echo-all \
-c "truncate table SCHEMA.TABLE1;" \
-c "\\copy SCHEMA.TABLE1 FROM '/opt/files/TABLE1.tsv' DELIMITER ';' CSV HEADER ENCODING 'UTF8' QUOTE '\"'" \
-c "truncate table SCHEMA.TABLE2;" \
-c "\\copy SCHEMA.TABLE2 FROM '/opt/files/TABLE2.tsv' DELIMITER ';' CSV HEADER ENCODING 'UTF8' QUOTE '\"'" \
${dbname} > ${log_file} 2>> ${log_file}
edit: all im getting right now is example below. How do i insert the text of variable ${path} ?
${psql_path}/psql \
-X \
--set ON_ERROR_STOP=on \
--set AUTOCOMMIT=on \
--echo-all \
-c "truncate table SCHEMA.TABLE1;" \
-c "\\copy SCHEMA.TABLE1 FROM '${path}/TABLE1.tsv' DELIMITER ';' CSV HEADER ENCODING 'UTF8' QUOTE '\"'" \
-c "truncate table SCHEMA.TABLE2;" \
-c "\\copy SCHEMA.TABLE2 FROM '${path}/TABLE2.tsv' DELIMITER ';' CSV HEADER ENCODING 'UTF8' QUOTE '\"'" \
${dbname} > ${log_file} 2>> ${log_file}
This line:
sql=$(cat sql.sql)
Will put contents of "sql.sql" into this variable $sql but won't evaluate any variables inside it. The right way to do this is to use a heredoc, instead. But since I figure out you want to keep your script, a simple solution would be:
sql=$(cat sql.sql | sed -e 's#${path}#'"${path}"'#')
This is simple running sed to substitute the contents of "${path}" into the contents of shell variable of the same name. But anyway consider using heredocs, because your "sql" file is obviously not SQL at all.
As advised, the HEREDOC is the best option and then simple parameter substitution can be done:
. properties
sql=$(cat sql.sql)
${psql_path}/psql <<-EOF
-X
--set ON_ERROR_STOP=on
--set AUTOCOMMIT=on
--echo-all
${sql//\$\{path\}/$path}
${dbname} > ${log_file} 2>> ${log_file}
EOF
Notice too that the line extensions are no longer required either. You should be able to remove them from sql.sql file as well

Making shapes with linux shell script

For an assignment, I'm trying to make a shell script that will print a triangle that looks like the following:
+
| \
| \
| \
| \
+-----
Here is my code in VIM:
echo'+
| \
| \
| \
| \
+----- '
However, instead of getting that as the output when I run the script, it outputs as the following:
Can anybody tell me what I'm doing wrong?
Try this
#!/bin/bash
echo '
+
| \
| \
| \
| \
+----- '
just start it on the next line since you need spaces before the "+"
How did your output got merged to 3 lines?
I think your original command was with a space after echo and double quotes:
echo "+
| \
| \
| \
| \
+----- "
And now pay attention to the last character of each line. When the last character is the \, the following line is appended to the current line.
Make sure each line ends with a space (or use single quotes).

Insert the line with special character (forward slash) in a file in shell script

Script to insert line in file
> cat text
BBLAYERS ?= " \
/home/neeraj/yocto/poky/meta \
/home/neeraj/yocto/poky/meta-yocto \
/home/neeraj/yocto/poky/meta-yocto-bsp \
"
In that I have to insert a line below a pattern as
> cat text
BBLAYERS ?= " \
/home/neeraj/yocto/poky/meta \
/home/neeraj/yocto/poky/meta-yocto \
/home/neeraj/yocto/poky/meta-yocto-bsp \
/home/neeraj/yocto/poky/meta-ti \
"
(Not tested)
Probably what you are looking for:
#!/bin/bash
awk -v search="$1" -v add="$2" '$0 ~ search{$0=$0"\n"add}1' "$3" >$4
exit
Where you would execute with the following format:
user#system:$ ./path-to-script.sh "Line you want to find" "Line you want to add" Input_File Output_File
Let me know if this needs more explanation. :-)

Resources