From 3c440ed820cb0a1f1f1c0ec20b9e563f9516f19f Mon Sep 17 00:00:00 2001 From: zkk <1007518571@qq.com> Date: Wed, 30 Oct 2024 09:14:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=96=AD=E7=94=B5=E7=BB=AD?= =?UTF-8?q?=E6=89=93=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/CreatBot_D1000/base.cfg | 63 +++++++++++++++++++- config/CreatBot_D600Pro2/base.cfg | 60 ++++++++++++++++++- config/CreatBot_F430NX/base.cfg | 61 ++++++++++++++++++- klippy/extras/gcode_shell_command.py | 87 ++++++++++++++++++++++++++++ klippy/extras/save_variables.py | 2 +- scripts/clear_plr.sh | 3 + scripts/plr.sh | 86 +++++++++++++++++++++++++++ 7 files changed, 356 insertions(+), 6 deletions(-) create mode 100644 klippy/extras/gcode_shell_command.py create mode 100644 scripts/clear_plr.sh create mode 100644 scripts/plr.sh diff --git a/config/CreatBot_D1000/base.cfg b/config/CreatBot_D1000/base.cfg index 7b7363205..04f13fba8 100644 --- a/config/CreatBot_D1000/base.cfg +++ b/config/CreatBot_D1000/base.cfg @@ -85,7 +85,7 @@ position_endstop: 0 position_max: 1000 homing_speed: 100 homing_retract_speed: 50 -second_homing_speed: 10 +second_homing_speed: 5 homing_retract_dist: 10 # homing_positive_dir: true @@ -392,10 +392,12 @@ gcode: [gcode_macro PROBE_SERVO_CLOSE] gcode: SET_SERVO SERVO=probe_servo angle=130 + [gcode_macro _START_PRINT_BASE] description: Call when starting to print gcode: - _RUNOUT_HANDLE + _CLEAR_LAST_FILE + _RUNOUT_HANDLE [gcode_macro START_PRINT] gcode: @@ -501,6 +503,7 @@ gcode: ######################################## # GCODE ######################################## + [gcode_macro G28] rename_existing: C28 gcode: @@ -592,6 +595,7 @@ gcode: ######################################## # CANCEL_PRINT/PAUSE/RESUME/ ######################################## + [gcode_macro _CLIENT_VARIABLE] variable_use_custom_pos : True variable_custom_park_x : 500.0 @@ -775,3 +779,58 @@ gcode: RESPOND TYPE=echo MSG='{"Noting! \"%s\" filament has been pulled out." % msg_extruder}' PAUSE {% endif %} + +######################################## +# power loss recovery +######################################## + +[delayed_gcode _CHECK_POWER_LOSS_RECOVERY] +initial_duration: 3.5 +gcode: + {% set was_interrupted = printer.save_variables.variables.was_interrupted | string %} + {% if was_interrupted == "True"%} + RESPOND TYPE=command MSG="action:prompt_begin " + RESPOND TYPE=command MSG="action:prompt_text The last print job was not completed continue printing?" + RESPOND TYPE=command MSG="action:prompt_footer_button Continue|_RESUME_INTERRUPTED" + RESPOND TYPE=command MSG="action:prompt_footer_button Cancel|_ABORT_INTERRUPTED|error" + RESPOND TYPE=command MSG="action:prompt_show" + {% endif %} + +[gcode_shell_command _CLEAR_PLR] +command: sh /home/klipper/klipper/scripts/clear_plr.sh +timeout: 5. +verbose: True + +[gcode_macro _CLEAR_LAST_FILE] +gcode: + {% set filename = '' %} + {% set filepath = '' %} + RUN_SHELL_COMMAND CMD=_CLEAR_PLR + SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' + SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' + {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% for var in zero_vars %} + SAVE_VARIABLE VARIABLE={var} VALUE=0 + {% endfor %} + SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False + +[gcode_shell_command _POWER_LOSS_RECOVERY] +command: /home/klipper/klipper/scripts/plr.sh +timeout: 420. +verbose: True + +[gcode_macro _RESUME_INTERRUPTED] +gcode: + RESPOND TYPE=command MSG="action:prompt_end" + SET_GCODE_OFFSET Z=0 MOVE=0 + {% set z_height = params.Z_HEIGHT|default(printer.save_variables.variables.power_resume_z)|float %} + {% set last_file = params.GCODE_FILE|default(printer.save_variables.variables.last_file)|string %} + M118 Initiating recovery of the last print task: {last_file} + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\"" + SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" + SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False + +[gcode_macro _ABORT_INTERRUPTED] +gcode: + RESPOND TYPE=command MSG="action:prompt_end" + _CLEAR_LAST_FILE diff --git a/config/CreatBot_D600Pro2/base.cfg b/config/CreatBot_D600Pro2/base.cfg index 9443dffd0..c13c6a6a5 100644 --- a/config/CreatBot_D600Pro2/base.cfg +++ b/config/CreatBot_D600Pro2/base.cfg @@ -85,7 +85,7 @@ position_endstop: 0 position_max: 600 homing_speed: 100 homing_retract_speed: 50 -second_homing_speed: 10 +second_homing_speed: 5 homing_retract_dist: 10 # homing_positive_dir: true @@ -396,7 +396,8 @@ gcode: [gcode_macro _START_PRINT_BASE] description: Call when starting to print gcode: - _RUNOUT_HANDLE + _CLEAR_LAST_FILE + _RUNOUT_HANDLE [gcode_macro START_PRINT] gcode: @@ -771,3 +772,58 @@ gcode: RESPOND TYPE=echo MSG='{"Noting! \"%s\" filament has been pulled out." % msg_extruder}' PAUSE {% endif %} + +######################################## +# power loss recovery +######################################## + +[delayed_gcode _CHECK_POWER_LOSS_RECOVERY] +initial_duration: 3.5 +gcode: + {% set was_interrupted = printer.save_variables.variables.was_interrupted | string %} + {% if was_interrupted == "True"%} + RESPOND TYPE=command MSG="action:prompt_begin " + RESPOND TYPE=command MSG="action:prompt_text The last print job was not completed continue printing?" + RESPOND TYPE=command MSG="action:prompt_footer_button Continue|_RESUME_INTERRUPTED" + RESPOND TYPE=command MSG="action:prompt_footer_button Cancel|_ABORT_INTERRUPTED|error" + RESPOND TYPE=command MSG="action:prompt_show" + {% endif %} + +[gcode_shell_command _CLEAR_PLR] +command: sh /home/klipper/klipper/scripts/clear_plr.sh +timeout: 5. +verbose: True + +[gcode_macro _CLEAR_LAST_FILE] +gcode: + {% set filename = '' %} + {% set filepath = '' %} + RUN_SHELL_COMMAND CMD=_CLEAR_PLR + SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' + SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' + {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% for var in zero_vars %} + SAVE_VARIABLE VARIABLE={var} VALUE=0 + {% endfor %} + SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False + +[gcode_shell_command _POWER_LOSS_RECOVERY] +command: /home/klipper/klipper/scripts/plr.sh +timeout: 420. +verbose: True + +[gcode_macro _RESUME_INTERRUPTED] +gcode: + RESPOND TYPE=command MSG="action:prompt_end" + SET_GCODE_OFFSET Z=0 MOVE=0 + {% set z_height = params.Z_HEIGHT|default(printer.save_variables.variables.power_resume_z)|float %} + {% set last_file = params.GCODE_FILE|default(printer.save_variables.variables.last_file)|string %} + M118 Initiating recovery of the last print task: {last_file} + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\"" + SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" + SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False + +[gcode_macro _ABORT_INTERRUPTED] +gcode: + RESPOND TYPE=command MSG="action:prompt_end" + _CLEAR_LAST_FILE diff --git a/config/CreatBot_F430NX/base.cfg b/config/CreatBot_F430NX/base.cfg index 3ea18ee44..62ad3ec11 100644 --- a/config/CreatBot_F430NX/base.cfg +++ b/config/CreatBot_F430NX/base.cfg @@ -520,7 +520,8 @@ gcode: [gcode_macro _START_PRINT_BASE] description: Call when starting to print gcode: - _RUNOUT_HANDLE + _CLEAR_LAST_FILE + _RUNOUT_HANDLE [gcode_macro START_PRINT] gcode: @@ -862,6 +863,7 @@ gcode: {% set _d = prompt_txt.append("\"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder) %} {% endif %} _ACT_RESUME DO_RESUME={do_resume} + [gcode_macro _ACT_RESUME] gcode: ##### get user parameters or use default ##### @@ -894,9 +896,11 @@ gcode: RESPOND TYPE=command MSG="action:prompt_footer_button Ok|RESPOND TYPE=command MSG=action:prompt_end|info" RESPOND TYPE=command MSG="action:prompt_show" {% endif %} + ######################################## # filament_runout ######################################## + [gcode_macro _FILAMENT_UPDATE] gcode: {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} @@ -936,3 +940,58 @@ gcode: RESPOND TYPE=echo MSG='{"Noting! \"%s\" filament has been pulled out." % msg_extruder}' PAUSE {% endif %} + +######################################## +# power loss recovery +######################################## + +[delayed_gcode _CHECK_POWER_LOSS_RECOVERY] +initial_duration: 3.5 +gcode: + {% set was_interrupted = printer.save_variables.variables.was_interrupted | string %} + {% if was_interrupted == "True"%} + RESPOND TYPE=command MSG="action:prompt_begin " + RESPOND TYPE=command MSG="action:prompt_text The last print job was not completed continue printing?" + RESPOND TYPE=command MSG="action:prompt_footer_button Continue|_RESUME_INTERRUPTED" + RESPOND TYPE=command MSG="action:prompt_footer_button Cancel|_ABORT_INTERRUPTED|error" + RESPOND TYPE=command MSG="action:prompt_show" + {% endif %} + +[gcode_shell_command _CLEAR_PLR] +command: sh /home/klipper/klipper/scripts/clear_plr.sh +timeout: 5. +verbose: True + +[gcode_macro _CLEAR_LAST_FILE] +gcode: + {% set filename = '' %} + {% set filepath = '' %} + RUN_SHELL_COMMAND CMD=_CLEAR_PLR + SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' + SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' + {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% for var in zero_vars %} + SAVE_VARIABLE VARIABLE={var} VALUE=0 + {% endfor %} + SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False + +[gcode_shell_command _POWER_LOSS_RECOVERY] +command: /home/klipper/klipper/scripts/plr.sh +timeout: 420. +verbose: True + +[gcode_macro _RESUME_INTERRUPTED] +gcode: + RESPOND TYPE=command MSG="action:prompt_end" + SET_GCODE_OFFSET Z=0 MOVE=0 + {% set z_height = params.Z_HEIGHT|default(printer.save_variables.variables.power_resume_z)|float %} + {% set last_file = params.GCODE_FILE|default(printer.save_variables.variables.last_file)|string %} + M118 Initiating recovery of the last print task: {last_file} + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\"" + SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" + SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False + +[gcode_macro _ABORT_INTERRUPTED] +gcode: + RESPOND TYPE=command MSG="action:prompt_end" + _CLEAR_LAST_FILE diff --git a/klippy/extras/gcode_shell_command.py b/klippy/extras/gcode_shell_command.py new file mode 100644 index 000000000..06ee857a4 --- /dev/null +++ b/klippy/extras/gcode_shell_command.py @@ -0,0 +1,87 @@ +# Run a shell command via gcode +# +# Copyright (C) 2019 Eric Callahan +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import os +import shlex +import subprocess +import logging + +class ShellCommand: + def __init__(self, config): + self.name = config.get_name().split()[-1] + self.printer = config.get_printer() + self.gcode = self.printer.lookup_object('gcode') + cmd = config.get('command') + cmd = os.path.expanduser(cmd) + self.command = shlex.split(cmd) + self.timeout = config.getfloat('timeout', 2., above=0.) + self.verbose = config.getboolean('verbose', True) + self.proc_fd = None + self.partial_output = "" + self.gcode.register_mux_command( + "RUN_SHELL_COMMAND", "CMD", self.name, + self.cmd_RUN_SHELL_COMMAND, + desc=self.cmd_RUN_SHELL_COMMAND_help) + + def _process_output(self, eventime): + if self.proc_fd is None: + return + try: + data = os.read(self.proc_fd, 10240) + except Exception: + pass + data = self.partial_output + data.decode() + if '\n' not in data: + self.partial_output = data + return + elif data[-1] != '\n': + split = data.rfind('\n') + 1 + self.partial_output = data[split:] + data = data[:split] + else: + self.partial_output = "" + self.gcode.respond_info(data) + + cmd_RUN_SHELL_COMMAND_help = "Run a linux shell command" + def cmd_RUN_SHELL_COMMAND(self, params): + gcode_params = params.get('PARAMS','') + gcode_params = shlex.split(gcode_params) + reactor = self.printer.get_reactor() + try: + proc = subprocess.Popen( + self.command + gcode_params, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + except Exception: + logging.exception( + "shell_command: Command {%s} failed" % (self.name)) + raise self.gcode.error("Error running command {%s}" % (self.name)) + if self.verbose: + self.proc_fd = proc.stdout.fileno() + self.gcode.respond_info("Running Command {%s}...:" % (self.name)) + hdl = reactor.register_fd(self.proc_fd, self._process_output) + eventtime = reactor.monotonic() + endtime = eventtime + self.timeout + complete = False + while eventtime < endtime: + eventtime = reactor.pause(eventtime + .05) + if proc.poll() is not None: + complete = True + break + if not complete: + proc.terminate() + if self.verbose: + if self.partial_output: + self.gcode.respond_info(self.partial_output) + self.partial_output = "" + if complete: + msg = "Command {%s} finished\n" % (self.name) + else: + msg = "Command {%s} timed out" % (self.name) + self.gcode.respond_info(msg) + reactor.unregister_fd(hdl) + self.proc_fd = None + + +def load_config_prefix(config): + return ShellCommand(config) \ No newline at end of file diff --git a/klippy/extras/save_variables.py b/klippy/extras/save_variables.py index 6cedcf466..2692ca3da 100644 --- a/klippy/extras/save_variables.py +++ b/klippy/extras/save_variables.py @@ -18,7 +18,7 @@ class SaveVariables: except self.printer.command_error as e: raise config.error(str(e)) gcode = self.printer.lookup_object('gcode') - gcode.register_command('SAVE_VARIABLE', self.cmd_SAVE_VARIABLE, + gcode.register_command('SAVE_VARIABLE', self.cmd_SAVE_VARIABLE, True, desc=self.cmd_SAVE_VARIABLE_help) def loadVariables(self): allvars = {} diff --git a/scripts/clear_plr.sh b/scripts/clear_plr.sh new file mode 100644 index 000000000..630804645 --- /dev/null +++ b/scripts/clear_plr.sh @@ -0,0 +1,3 @@ +if [ -d ~/printer_data/gcodes/.plr ]; then + rm -rf ~/printer_data/gcodes/.plr +fi diff --git a/scripts/plr.sh b/scripts/plr.sh new file mode 100644 index 000000000..5a4a92239 --- /dev/null +++ b/scripts/plr.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# $1 z_height $2 filename + +mkdir -p ~/printer_data/gcodes/.plr +filepath=$(sed -n "s/.*filepath *= *'\([^']*\)'.*/\1/p" /home/klipper/printer_data/config/config_variables.cfg) +filepath=$(printf "$filepath") +echo "$filepath" + +last_file=$(sed -n "s/.*last_file *= *'\([^']*\)'.*/\1/p" /home/klipper/printer_data/config/config_variables.cfg) +last_file=$(printf "$last_file") +echo "$last_file" +plr=$last_file +echo "plr=$plr" +PLR_PATH=~/printer_data/gcodes/.plr + +file_content=$(cat "${filepath}" | awk '/; thumbnail begin/{flag=1;next}/; thumbnail end/{flag=0} !flag' | grep -v "^;simage:\|^;gimage:") + +echo "$file_content" | sed 's/\r$//' | awk -F"Z" 'BEGIN{OFS="Z"} {if ($2 ~ /^[0-9]+$/) $2=$2".0"} 1' > /home/klipper/plrtmpA.$$ +sed -i 's/Z\./Z0\./g' /home/klipper/plrtmpA.$$ +cat /home/klipper/plrtmpA.$$ | sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' | grep -m 1 ' Z' | sed -ne 's/.* Z\([^ ]*\).*/SET_KINEMATIC_POSITION Z=\1/p' > ${PLR_PATH}/"${plr}" + + +cat /home/klipper/plrtmpA.$$ | sed '/ Z'${1}'/q' | sed -ne '/\(M104\|M140\|M109\|M190\|M106\)/p' >> ${PLR_PATH}/"${plr}" + +line=$(cat /home/klipper/plrtmpA.$$ | sed '/ Z'${1}'/q' | sed -n '/START_PRINT/p') + +if [ -n "$line" ]; then + EXTRUDER=$(echo "$line" | sed -n 's/.*EXTRUDER=\([0-9]*\).*/\1/p') + EXTRUDER1=$(echo "$line" | sed -n 's/.*EXTRUDER1=\([0-9]*\).*/\1/p') + BED=$(echo "$line" | sed -n 's/.*BED=\([0-9]*\).*/\1/p') + CHAMBER=$(echo "$line" | sed -n 's/.*CHAMBER=\([0-9]*\).*/\1/p') + EXTRUDER=${EXTRUDER:-0} + EXTRUDER1=${EXTRUDER1:-0} + BED=${BED:-0} + CHAMBER=${CHAMBER:-0} + + temp_cmds=("M140 S" "M104 T0 S" "M104 T1 S" "M141 S" "M190 S" "M109 T0 S" "M109 T1 S" "M191 S") + temps=("$BED" "$EXTRUDER" "$EXTRUDER1" "$CHAMBER" "$BED" "$EXTRUDER" "$EXTRUDER1" "$CHAMBER") + + for i in "${!temps[@]}"; do + if [ "${temps[$i]}" != "0" ]; then + echo "${temp_cmds[$i]} ${temps[$i]}" >> "${PLR_PATH}/${plr}" + fi + done +fi + + +cat /home/klipper/plrtmpA.$$ | sed -ne '/;End of Gcode/,$ p' | tr '\n' ' ' | sed -ne 's/ ;[^ ]* //gp' | sed -ne 's/\\\\n/;/gp' | tr ';' '\n' | grep material_bed_temperature | sed -ne 's/.* = /M140 S/p' | head -1 >> ${PLR_PATH}/"${plr}" +cat /home/klipper/plrtmpA.$$ | sed -ne '/;End of Gcode/,$ p' | tr '\n' ' ' | sed -ne 's/ ;[^ ]* //gp' | sed -ne 's/\\\\n/;/gp' | tr ';' '\n' | grep material_print_temperature | sed -ne 's/.* = /M104 S/p' | head -1 >> ${PLR_PATH}/"${plr}" +cat /home/klipper/plrtmpA.$$ | sed -ne '/;End of Gcode/,$ p' | tr '\n' ' ' | sed -ne 's/ ;[^ ]* //gp' | sed -ne 's/\\\\n/;/gp' | tr ';' '\n' | grep material_bed_temperature | sed -ne 's/.* = /M190 S/p' | head -1 >> ${PLR_PATH}/"${plr}" +cat /home/klipper/plrtmpA.$$ | sed -ne '/;End of Gcode/,$ p' | tr '\n' ' ' | sed -ne 's/ ;[^ ]* //gp' | sed -ne 's/\\\\n/;/gp' | tr ';' '\n' | grep material_print_temperature | sed -ne 's/.* = /M109 S/p' | head -1 >> ${PLR_PATH}/"${plr}" + + +BG_EX=`tac /home/klipper/plrtmpA.$$ | sed -e '/ Z'${1}'[^0-9]*$/q' | tac | tail -n+2 | sed -e '/ Z[0-9]/ q' | tac | sed -e '/ E[0-9]/ q' | sed -ne 's/.* E\([^ ]*\)/G92 E\1/p'` +# If we failed to match an extrusion command (allowing us to correctly set the E axis) prior to the matched layer height, then simply set the E axis to the first E value present in the resemued gcode. This avoids extruding a huge blod on resume, and/or max extrusion errors. +if [ "${BG_EX}" = "" ]; then + BG_EX=`tac /home/klipper/plrtmpA.$$ | sed -e '/ Z'${1}'[^0-9]*$/q' | tac | tail -n+2 | sed -ne '/ Z/,$ p' | sed -e '/ E[0-9]/ q' | sed -ne 's/.* E\([^ ]*\)/G92 E\1/p'` +fi +M83=$(cat /home/klipper/plrtmpA.$$ | sed '/ Z'${1}'/q' | sed -ne '/\(M83\)/p') +if [ -n "${M83}" ];then + echo 'G92 E0' >> ${PLR_PATH}/"${plr}" + echo ${M83} >> ${PLR_PATH}/"${plr}" +else + echo ${BG_EX} >> ${PLR_PATH}/"${plr}" +fi +echo 'G91' >> ${PLR_PATH}/"${plr}" +echo 'G1 Z10' >> ${PLR_PATH}/"${plr}" +echo 'G90' >> ${PLR_PATH}/"${plr}" +echo 'G28 X Y' >> ${PLR_PATH}/"${plr}" +cat /home/klipper/plrtmpA.$$ | sed '/ Z'${1}'/q' | sed -ne '/\(ACTIVATE_COPY_MODE\|ACTIVATE_MIRROR_MODE\)/p' >> ${PLR_PATH}/"${plr}" +echo 'G1 X5' >> ${PLR_PATH}/"${plr}" +echo 'G1 Y5' >> ${PLR_PATH}/"${plr}" +echo 'G91' >> ${PLR_PATH}/"${plr}" +echo 'G1 Z-5' >> ${PLR_PATH}/"${plr}" +echo 'G90' >> ${PLR_PATH}/"${plr}" +echo 'M106 S204' >> ${PLR_PATH}/"${plr}" + +#tac /home/klipper/plrtmpA.$$ | sed -e '/ Z'${1}'[^0-9]*$/q' | tac | tail -n+2 | sed -ne '/ Z/,$ p' >> ${PLR_PATH}/"${plr}" +first_line=$(cat /home/klipper/plrtmpA.$$ |sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' | grep -m 1 ' Z' | grep -E 'F[0-9]+' | sed -E 's/F[0-9]+/F3000/g') +if [ "${first_line}" = "" ];then + cat /home/klipper/plrtmpA.$$ | sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' >> ${PLR_PATH}/"${plr}" +else + echo ${first_line} >> ${PLR_PATH}/"${plr}" + cat /home/klipper/plrtmpA.$$ | sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' | tail -n +2 >> ${PLR_PATH}/"${plr}" +fi +rm /home/klipper/plrtmpA.$$