जैसे ही वे चलाए जाते हैं, मैं एक bash स्क्रिप्ट से केवल कुछ कमांड कैसे प्रिंट कर सकता हूं?


19

मेरे पास कई बैश स्क्रिप्ट हैं यदि कमांड लाइन के तर्कों के आधार पर बयान देते हैं, जब मैं इसे कॉल करता हूं। कुछ प्रकार के आउटपुट के रूप में जो कमांड चलाए जा रहे हैं, उन सभी के माध्यम से प्रवाह की पुष्टि करने में मददगार है यदि कथन हैं, लेकिन मेरा वर्तमान समाधान मुझे बहुत अधिक जानकारी दे रहा है।

set -vस्क्रिप्ट में स्क्रीन पर मुद्रित कमांड को देखने के लिए स्क्रिप्ट का उपयोग करना कुछ हद तक मददगार था क्योंकि वे स्क्रिप्ट में चलाए जाते थे, हालांकि मुझे बहुत अधिक कमांड मिलते हैं । यह लगभग पूरी स्क्रिप्ट की कॉपी की तरह है।

मैं आउटपुट चाहता हूं जो यह दर्शाता है कि कमांड क्या चल रहे हैं, लेकिन मैं टिप्पणियों, नई लाइनों, अगर स्टेटमेंट आदि में अभिव्यक्ति नहीं देखना चाहता हूं।

क्या कोई तरीका है जो मैं प्रिंट होने से पहले पहले regex के माध्यम से -v विकल्प द्वारा उत्पन्न सभी संभावित आउटपुट पास कर सकता हूं? या कुछ अन्य समाधान के लिए केवल एक निश्चित "प्रकार" (उदाहरण के लिए कि निष्पादन योग्य का उपयोग कर रहे हैं और न केवल विशिष्ट बयान, टिप्पणी आदि का उपयोग कर रहे हैं?)

[१] /programming/257616/sudo-changes-path-why इस पर काफी मददगार था और मुझे इसके set -vउपयोग के लिए सुझाव मिला ।

संपादित करें :

एक समान (लेकिन समान नहीं) स्क्रिप्ट जो मैं चला रहा हूं:

#!/bin/bash

#get verbose command output
set -v

env=$1

if [ "$env" == "dev" ]; then
    python ascript.py
fi

if [ "$env" == "prod" ]; then

    #launching in prod will most likely fail if not run as root. Warn user if not running as root.
    if [ $EUID -ne 0 ]; then
        echo "It doesn't look like you're running me as root. This probably won't work. Press any key to continue." > /dev/stderr
        read input
    fi

    #"stop" any existing nginx processes
    pkill -f nginx

    nginx -c `pwd`/conf/artfndr_nginx.conf

fi

मैं इस स्क्रिप्ट से आउटपुट लाइनों के केवल 2 संभव सेट चाहता हूं। सबसे पहला:

python ascript.py

द्वितीय:

pkill -f nginx
nginx -c /some/current/directory/conf/artfndr_nginx.conf

1
बेशक आप इसे पार्स कर सकते हैं लेकिन हम तब तक आपकी मदद नहीं कर सकते जब तक आप हमें स्क्रिप्ट नहीं दिखाते हैं और समझाते set -vहैं कि आपको आउटपुट के कौन से हिस्से चाहिए और कौन से नहीं।
terdon

जवाबों:


12

जब मैं अधिक जटिल बैश स्क्रिप्ट लिखता हूं, तो मैं कमांड चलाने के लिए एक छोटे से फ़ंक्शन का उपयोग करता हूं जो कमांड को लॉगफ़ाइल में चलाने के लिए प्रिंट करेगा:

runthis(){
    ## print the command to the logfile
    echo "$@" >> $LOG
    ## run the command and redirect it's error output
    ## to the logfile
    eval "$@" 2>> $LOG 
}

फिर, मेरी स्क्रिप्ट में, मैं इस तरह से कमांड चलाता हूं:

runthis "cp /foo/bar /baz/"

यदि आप एक कमांड प्रिंट नहीं चाहते हैं, तो इसे सामान्य रूप से चलाएं।

आप या तो $LOGफ़ाइल नाम पर सेट कर सकते हैं या बस इसे हटा सकते हैं और प्रिंटआउट या स्टडर पर प्रिंट कर सकते हैं।


+1 इसके अलावा, मैं फ़ंक्शन के एक लघु-नामित संस्करण के साथ "महत्वपूर्ण" कमांडों को केवल प्रचलित करके अपनी स्क्रिप्ट के अंदर इसे चलाने में सक्षम था, इसलिए पंक्तियों v python ascript.pyको उद्धरणों में संलग्न किए बिना और अपने vim कोड हाइलाइटिंग खो जाने के बिना कुछ ऐसा दिखता है
Trindia

@Trindaz आपके कमांड में वैरिएबल पास करने की आवश्यकता होने पर कोटेशन होते हैं, यदि वैरिएबल में रिक्त स्थान होते हैं तो आपको समस्याएँ हो सकती हैं।
terdon

eval ..... || ok=1: "1" तक ही सेट होगा जब "eval ..." फेल हो जाएगा ?? शायद आपका मतलब "&&" था? और अगर आपका मतलब है कि, eval लाइन से पहले एक "ok = 0" जोड़ें, तो यह हर बार "रीसेट" होता है। या बस "त्रुटि" में "ठीक" का नाम बदलें? ऐसा लगता है कि यहाँ क्या था। तो अंत में:eval "$@" 2>> "$LOG" && error=0 || error=1
ओलिवियर दुलैक

@OlivierDulac, इसके उपयोग के संस्करण में, मेरे पास एक okचर है जो स्क्रिप्ट को रोक देगा यदि कोई भी कमांड विफल हो जाती है। चूँकि यहाँ प्रासंगिक नहीं था, मैंने इसे हटा दिया लेकिन हटाना नहीं भूली || ok=1। धन्यवाद, अब तय किया गया।
terdon

उत्कृष्ट समाधान! मुझे "आसपास के निष्कासन कथन को हटाना पड़ा , क्योंकि कमांड पहले से ही "s
gromit190

11

एक उप-शेल का उपयोग करें, अर्थात:

( set -x; cmd1; cmd2 )

उदाहरण के लिए:

( set -x; echo "hi there" )

प्रिंट

+ echo 'hi there'
hi there

मैं इसे set -x; cmd; set +xकई कारणों से पसंद करता हूं । पहले, यह उस set -xस्थिति में रीसेट नहीं होता है जब यह पहले होता है। दूसरा, स्क्रिप्ट को समाप्त करने से जाल का कारण नहीं बनता है, पर क्रिया सेटिंग्स के साथ निष्पादित किया जाता है।
ओलिवर गोंडेज़ा

2

मैंने @ टेर्डन के समान विधियों का उपयोग किया है। यह उच्चतर स्तर की प्रोग्रामिंग लैंग्वेज को लॉगर कहते हैं, और पूर्ण विकसित लाइब्रेरियों जैसे कि log4J (जावा), log4Perl (पर्ल) आदि की शुरुआत है।

set -xजैसा कि आपने उल्लेख किया है, आप बैश में भी ऐसा ही कुछ प्राप्त कर सकते हैं, लेकिन आप इसका उपयोग कोडिंग ब्लॉक को कमांड के एक सबसेट को डिबगिंग को चालू करने के लिए कर सकते हैं ताकि उनके साथ कोड को ब्लॉक किया जा सके।

$ set -x; cmd1; cmd2; set +x

उदाहरण

यहां एक लाइनर पैटर्न है जिसका आप उपयोग कर सकते हैं।

$ set -x; echo  "hi" ;set +x
+ echo hi
hi
+ set +x

आप एक स्क्रिप्ट में कई कमांड्स के लिए उन्हें इस तरह लपेट सकते हैं।

set -x
cmd1
cmd2
set +x

cmd3

Log4Bash

ज्यादातर लोग बेखबर होते हैं लेकिन बैश के पास भी एक Log4 * होता है, Log4Bash । यदि आपके पास अधिक मामूली जरूरत है तो इसे स्थापित करने के लिए समय की कीमत हो सकती है।

log4bash बैश स्क्रिप्ट के लिए बेहतर लॉगिंग करने का प्रयास है (यानी बैश चूसना में लॉगिंग कम करें)।

उदाहरण

यहाँ log4bash का उपयोग करने के कुछ उदाहरण दिए गए हैं।

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";

Log4sh

यदि आप चाहते हैं कि मैं एक log4 * फ्रेमवर्क की पूरी शक्ति के रूप में क्या वर्गीकृत करूँगा तो मैं Log4sh को आज़माऊंगा

अंश

log4sh मूल रूप से एक लॉगिंग समस्या को हल करने के लिए विकसित किया गया था, जिसमें मैंने कुछ ऐसे उत्पादन परिवेशों में काम किया था, जहां मैंने काम किया है या तो मेरे पास बहुत अधिक लॉगिंग थी, या पर्याप्त नहीं थी। विशेष रूप से क्रोन नौकरियों ने मुझे अपने निरंतर और कष्टप्रद ईमेल के साथ सबसे अधिक सिरदर्द दिया, जो मुझे बताता है कि सब कुछ काम किया है, या यह कि कुछ भी काम नहीं किया है, लेकिन एक विस्तृत कारण क्यों नहीं। मैं अब वातावरण में log4sh का उपयोग करता हूं, जहां शेल स्क्रिप्ट से लॉगिंग महत्वपूर्ण है, लेकिन जहां मुझे एक साधारण "हैलो, मुझे ठीक करें" से अधिक की आवश्यकता है! लॉगिंग संदेश का प्रकार। यदि आपको वह दिखाई देता है जो आप देखते हैं, या सुधार के बारे में कोई सुझाव है, तो कृपया मुझे ईमेल छोड़ने के लिए स्वतंत्र महसूस करें। यदि परियोजना में पर्याप्त रुचि है, तो मैं इसे और विकसित करूंगा।

log4sh को लिनक्स पर बॉर्न अगेन शेल (/ बिन / बैश) के तहत विकसित किया गया है, लेकिन यह सुनिश्चित करने के लिए बहुत ध्यान रखा गया है कि यह सोलारिस के डिफ़ॉल्ट बॉर्न शेल (/ बिन / श) के तहत काम करता है क्योंकि यह प्राथमिक उत्पादन होता है मंच अपने आप से इस्तेमाल किया।

Log4sh कई गोले का समर्थन करता है, न कि सिर्फ बैश।

  • बॉर्न शेल (sh)
  • बैश - जीएनयू बॉर्न अगेन SHell (bash)
  • DASH (डैश)
  • कोर्न शेल (ksh)
  • pdksh - सार्वजनिक डोमेन Korn Shell (pdksh)

यह सिर्फ लिनक्स ही नहीं, बल्कि कई ओएस पर भी टेस्ट किया गया है।

  • साइगविन (विंडोज के तहत)
  • FreeBSD (उपयोगकर्ता समर्थित)
  • लिनक्स (जेंटू, रेडहैट, उबंटू)
  • मैक ओएस एक्स
  • सोलारिस 8, 9, 10

लॉग 4 * फ्रेमवर्क का उपयोग करने के लिए सीखने में कुछ समय लगेगा लेकिन अगर आप अपने लॉगिंग से अधिक मांग की आवश्यकता रखते हैं तो यह इसके लायक है। Log4sh एक कॉन्फ़िगरेशन फ़ाइल का उपयोग करता है जहां आप ऐपेंडर्स को परिभाषित कर सकते हैं और दिखाई देने वाले आउटपुट के लिए स्वरूपण को नियंत्रित कर सकते हैं।

उदाहरण

#! /bin/sh
#
# log4sh example: Hello, world
#

# load log4sh (disabling properties file warning) and clear the default
# configuration
LOG4SH_CONFIGURATION='none' . ./log4sh
log4sh_resetConfiguration

# set the global logging level to INFO
logger_setLevel INFO

# add and configure a FileAppender that outputs to STDERR, and activate the
# configuration
logger_addAppender stderr
appender_setType stderr FileAppender
appender_file_setFile stderr STDERR
appender_activateOptions stderr

# say Hello to the world
logger_info 'Hello, world'

अब जब मैं इसे चलाता हूं:

$ ./log4sh.bash 
INFO - Hello, world

नोट: उपरोक्त कोड के भाग के रूप में परिशिष्ट को कॉन्फ़िगर करता है। यदि आप इसे पसंद करते हैं तो इसे अपनी फ़ाइल log4sh.propertiesआदि में निकाला जा सकता है ।

यदि आपको अधिक जानकारी की आवश्यकता है, तो Log4sh के लिए उत्कृष्ट प्रलेखन से परामर्श करें ।


जोड़े गए नोटों के लिए धन्यवाद, लेकिन मेरे पास मुख्य समस्या यह है कि सभी setआज्ञाओं को मुझे पेश करना होगा, टिप्पणियों के आसपास बारी-बारी से आदि, इसलिए मेरी स्क्रिप्ट के शीर्ष पर एक फ़ंक्शन होने के साथ, एक एकल वर्ण फ़ंक्शन कॉल के लिए पूर्वनिर्मित स्क्रिप्ट की सभी "महत्वपूर्ण" पंक्तियाँ मुझे अब के लिए पुरानी लगती हैं। (सिंगल कैरेक्टर क्योंकि फंक्शन का एक ही कैरेक्टर नाम है)
Trindaz

@ तिंदाज़ - क्षमा करें, मैंने अपना उत्तर अभी तक समाप्त नहीं किया है। Log4bash पर एक नज़र डालें यदि आपके पास अधिक जरूरत है जो कि फ़ंक्शन टेर्डन ने दी है।
slm

1
@ टिंडाज - मैं समय-समय पर कुछ ऐसा ही करता हूं, मैंने जो दूसरा तरीका इस्तेमाल किया है वह echoअपने स्वयं के फ़ंक्शन में लपेटने के लिए है mecho, और फिर -vजब मैं चीजों को बंद करना चाहता हूं, तो वर्बोज़ नामक कार्यक्रम में एक स्विच पास करें । मैं इसे 2 तर्क स्विच के साथ भी नियंत्रित कर सकता हूं जो फ़ंक्शन का नाम निर्दिष्ट करता है, इसलिए मेरे पास 2 अक्ष हैं, जिस पर लॉगिंग को नियंत्रित करना है। यह अक्सर log4bash चाहने के लिए प्रवेश द्वार है।
SLM

1
@Trindaz set -xकमांड निष्पादित करता है क्योंकि वे निष्पादित होते हैं। यह टिप्पणी नहीं छापता है। set -xडिबगिंग के लिए व्यावहारिक है (इसके विपरीत set -vजो बहुत उपयोगी नहीं है)। Zash में set -xबैश की तुलना में बेहतर आउटपुट है , उदाहरण के लिए यह दिखाता है कि वर्तमान में किस फ़ंक्शन को निष्पादित किया जा रहा है और स्रोत लाइन नंबर।
गिल्स एसओ- बुराई का होना बंद करो '

धन्यवाद @Gilles सच है, लेकिन यह मुझे अभिव्यक्ति के विस्तार, जो इस मामले में overkill था
Trindaz

1

आप चर काtrap DEBUG परीक्षण कर सकते BASH_COMMANDहैं । इसे स्क्रिप्ट के शीर्ष पर जोड़ें:

log() {
    case "$1" in
        python\ *)
            ;&
        pkill\ *)
            printf "%s\n" "$*"
            ;;
    esac
}

trap 'log "$BASH_COMMAND"' DEBUG

कोड पठनीय है; यह केवल तभी परीक्षण करता है जब पहला तर्क इसके साथ शुरू होता है, pythonया pkillयदि यह मामला है तो इसे प्रिंट करता है। और जाल BASH_COMMANDपहले तर्क के रूप में (जिसमें कमांड निष्पादित किया जाएगा) का उपयोग करता है।

$ bash foo.sh dev
python ascript.py
python: can't open file 'ascript.py': [Errno 2] No such file or directory
$ bash foo.sh prod
It doesn't look like you're running me as root. This probably won't work. Press any key to continue.

pkill -f nginx
foo.sh: line 32: nginx: command not found

ध्यान दें कि caseग्लब्स का उपयोग करते समय , आप आसानी से कर सकते हैं:

if [[ $1 =~ python|nginx ]]
then
    printf "%s" "$*"
fi

और नियमित अभिव्यक्ति का उपयोग करें।


0

यह स्टीवन पेनी के स्वच्छ समारोह का एक संशोधित संस्करण है। यह रंग में अपने तर्कों को छापता है और आवश्यकतानुसार उन्हें उद्धृत करता है। इसे चुनिंदा कमांड्स को ट्रेस करने के लिए चुनिए। चूंकि उद्धरण आउटपुट हैं, आप किसी स्क्रिप्ट को डीबग करते समय तत्काल पुन: निष्पादन के लिए मुद्रित लाइनों को कॉपी कर सकते हैं और उन्हें टर्मिनल पर पेस्ट कर सकते हैं। मैंने क्या और क्यों बदला यह जानने के लिए पहली टिप्पणी पढ़ें।

xc() # $@-args
{
  cecho "$@"
  "$@"
}
cecho() # $@-args
{
  awk '
  BEGIN {
    x = "\047"
    printf "\033[36m"
    while (++i < ARGC) {
      if (! (y = split(ARGV[i], z, x))) {
        printf (x x)
      } else {
        for (j = 1; j <= y; j++) {
          printf "%s", z[j] ~ /[^[:alnum:]%+,./:=@_-]/ ? (x z[j] x) : z[j]
          if (j < y) printf "\\" x
        }
      }
      printf i == ARGC - 1 ? "\033[m\n" : FS
    }
  }
  ' "$@"
}

आउटपुट के साथ उदाहरण का उपयोग:

# xc echo "a b" "c'd" "'" '"' "fg" '' " " "" \# this line prints in green

echo 'a b' c\'d \' '"' fg '' ' ' '' '#' this line prints in green

a b c'd ' " fg # this line prints in green

हरे रंग में प्रिंट के ऊपर दूसरी लाइन और तीसरी लाइन को पुन: पेश करने के लिए कॉपी-पेस्ट किया जा सकता है।

आगे की टिप्पणी

@ स्टीवन-पेनी का मूल एक्ससी चालाक है और वह इसके लिए सभी क्रेडिट का हकदार है। हालाँकि, मैंने कुछ मुद्दों पर गौर किया, लेकिन मैं उनकी पोस्ट पर सीधे टिप्पणी नहीं कर सका क्योंकि मेरे पास पर्याप्त प्रतिष्ठा नहीं है। इसलिए मैंने उनके पद के लिए एक सुझाव संपादित किया लेकिन समीक्षकों ने मेरा संपादन अस्वीकार कर दिया। इसलिए मैंने इस उत्तर के रूप में अपनी टिप्पणियों को पोस्ट करने का सहारा लिया, हालांकि मैं स्टीव पेनी के स्वयं के उत्तर को संपादित करने में सक्षम होना पसंद करूंगा।

मैंने स्टीवन-पेनी के जवाब को बदल दिया

फिक्स्ड: मुद्रण अशक्त तार - वे मुद्रित नहीं थे। फिक्स्ड: मुद्रण स्ट्रिंग्स जिसमें शामिल हैं %- वे अजीब वाक्यविन्यास त्रुटियों का कारण बने। के for (j in ...)साथ प्रतिस्थापित for (j = 0, ...)क्योंकि पूर्व सरणी ट्रैवर्सल के आदेश की गारंटी नहीं देता है (यह कार्यान्वयन-निर्भर है)। पोर्टेबिलिटी के लिए 0 से अष्टक संख्या में जोड़ा गया।

अपडेट करें

स्टीवन पेनी ने तब से उन मुद्दों को अपने जवाब में तय किया है, इसलिए ये टिप्पणियां केवल मेरे उत्तर के ऐतिहासिक रिकॉर्ड के लिए ही रहती हैं। अधिक जानकारी के लिए टिप्पणियाँ अनुभाग देखें।


0

आप चलने से पहले रंग को कमांड प्रिंट करने के लिए POSIX stdlib लाइब्रेरी से "sh_trace" शेल फ़ंक्शन का उपयोग कर सकते हैं । उदाहरण:

पूर्वावलोकन

अंडरकवरिंग अवेक फंक्शन:

function sh_trace(ary,   b, d, k, q, w, z) {
  b = "\47"
  for (d in ary) {
    k = split(ary[d], q, b)
    q[1]
    if (d - 1)
      z = z " "
    for (w in q) {
      z = z (!k || q[w] ~ "[^[:alnum:]%+,./:=@_-]" ? b q[w] b : q[w]) \
      (w < k ? "\\" b : "")
    }
  }
  printf "\33[36m%s\33[m\n", z
  system(z)
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.