Bash: ข้อผิดพลาดทางไวยากรณ์: การเปลี่ยนเส้นทางที่ไม่คาดคิด


141

ฉันทำสิ่งนี้ในสคริปต์:

read direc <<< $(basename `pwd`)

และฉันได้รับ:

Syntax error: redirection unexpected

ในเครื่องอูบุนตู

/bin/bash --version
GNU bash, version 4.0.33(1)-release (x86_64-pc-linux-gnu)

ในขณะที่ฉันไม่ได้รับข้อผิดพลาดนี้ในเครื่อง suse อื่น:

/bin/bash --version
GNU bash, version 3.2.39(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.

เหตุใดจึงเกิดข้อผิดพลาด


สำหรับการอ้างอิงคำสั่งจะทำงานบน cygwin เช่นกัน (/ bin / bash --version GNU bash เวอร์ชัน 3.2.49 (23) - ปล่อย (i686-pc-cygwin) ลิขสิทธิ์ (C) 2007 Free Software Foundation, Inc. )
hlovdal

คำตอบ:


253

สคริปต์ของคุณอ้างอิง/bin/bashหรือ/bin/shอยู่ในบรรทัดแฮชแบงหรือไม่ เชลล์ระบบเริ่มต้นใน Ubuntu คือเส้นประไม่ใช่ทุบตีดังนั้นหากคุณมี#!/bin/shสคริปต์ของคุณจะใช้เชลล์ที่แตกต่างจากที่คุณคาดไว้ Dash ไม่มีตัว<<<ดำเนินการเปลี่ยนเส้นทาง


16

นักเทียบท่า:

ฉันได้รับปัญหานี้จาก Dockerfile เหมือนที่ฉันมี:

RUN bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

อย่างไรก็ตามตามปัญหานี้ได้รับการแก้ไข:

execรูปแบบทำให้มันเป็นไปได้ที่จะหลีกเลี่ยง munging สตริงเปลือกและคำสั่งโดยใช้ภาพฐานที่ไม่ได้มีRUN /bin/sh

บันทึก

ในการใช้เชลล์อื่นนอกเหนือจาก/bin/shนั้นให้ใช้ฟอร์มexec ที่ส่งผ่านในเชลล์ที่ต้องการ ตัวอย่างเช่น,

RUN ["/bin/bash", "-c", "echo hello"]

วิธีการแก้:

RUN ["/bin/bash", "-c", "bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)"]

สังเกตเครื่องหมายคำพูดรอบ ๆพารามิเตอร์แต่ละตัว


16

หากคุณกำลังใช้สิ่งต่อไปนี้เพื่อเรียกใช้สคริปต์ของคุณ:

sudo sh ./script.sh

จากนั้นคุณจะต้องใช้สิ่งต่อไปนี้แทน:

sudo bash ./script.sh

เหตุผลก็คือ Bash ไม่ใช่เชลล์เริ่มต้นสำหรับ Ubuntu ดังนั้นหากคุณใช้ "sh" มันก็จะใช้เชลล์เริ่มต้น ซึ่งจริงๆแล้ว Dash สิ่งนี้จะเกิดขึ้นไม่ว่าคุณจะ#!/bin/bashอยู่ที่ด้านบนสุดของสคริปต์ก็ตาม ด้วยเหตุนี้คุณจะต้องระบุอย่างชัดเจนเพื่อใช้bashดังที่แสดงด้านบนและสคริปต์ของคุณควรทำงานตามที่คาดไว้

Dash ไม่รองรับการเปลี่ยนเส้นทางเช่นเดียวกับ Bash


6

คุณสามารถรับผลลัพธ์ของคำสั่งนั้นและใส่ไว้ในตัวแปร heredocการใช้งานแล้ว ตัวอย่างเช่น:

nc -l -p 80 <<< "tested like a charm";

สามารถเขียนได้เช่น:

nc -l -p 80 <<EOF
tested like a charm
EOF

และแบบนี้ (นี่คือสิ่งที่คุณต้องการ):

text="tested like a charm"
nc -l -p 80 <<EOF
$text
EOF

ตัวอย่างการปฏิบัติในbusyboxใต้dockerภาชนะ:

kasra@ubuntu:~$ docker run --rm -it busybox
/ # nc -l -p 80 <<< "tested like a charm";
sh: syntax error: unexpected redirection


/ # nc -l -p 80 <<EOL
> tested like a charm
> EOL
^Cpunt!       => socket listening, no errors. ^Cpunt! is result of CTRL+C signal.


/ # text="tested like a charm"
/ # nc -l -p 80 <<EOF
> $text
> EOF
^Cpunt!

... หรือecho 'text' | ncที่สั้นกว่านั้น
phil294


1

อีกสาเหตุหนึ่งของข้อผิดพลาดอาจเป็นถ้าคุณกำลังเรียกใช้งาน cron ที่อัปเดตสำเนาการทำงานที่โค่นล้มจากนั้นได้พยายามเรียกใช้สคริปต์เวอร์ชันที่อยู่ในสถานะขัดแย้งกันหลังการอัปเดต ...


1

bashในเครื่องของฉันถ้าฉันเรียกใช้สคริปต์โดยตรงเริ่มต้นคือ

ถ้าฉันรันด้วยsudoค่าเริ่มต้นคือsh.

sudoนั่นเป็นเหตุผลที่ผมถูกตีปัญหานี้เมื่อฉันใช้


0

ในกรณีของฉันเกิดข้อผิดพลาดเนื่องจากฉันใส่ ">>" สองครั้ง

mongodump --db=$DB_NAME --collection=$col --out=$BACKUP_LOCATION/$DB_NAME-$BACKUP_DATE >> >> $LOG_PATH

ฉันแค่แก้ไขเป็น

mongodump --db=$DB_NAME --collection=$col --out=$BACKUP_LOCATION/$DB_NAME-$BACKUP_DATE >> $LOG_PATH

0

ก่อนรันสคริปต์คุณควรตรวจสอบบรรทัดแรกของเชลล์สคริปต์สำหรับล่าม

เช่น: ถ้าสคริปต์ขึ้นต้นด้วย / bin / bash ให้รันสคริปต์โดยใช้คำสั่งด้านล่าง "bash script_name.sh"

หากสคริปต์เริ่มต้นด้วย / bin / sh ให้รันสคริปต์โดยใช้คำสั่งด้านล่าง "sh script_name.sh"

./sample.sh - จะตรวจหาตัวแปลจากบรรทัดแรกของสคริปต์และเรียกใช้

ลินุกซ์ดิสทริบิวชันต่างกันที่มีเชลล์ต่างกันเป็นค่าเริ่มต้น


1
แม้ว่าเราจะขอบคุณสำหรับคำตอบของคุณ แต่จะดีกว่าถ้าคำตอบนั้นให้คุณค่าเพิ่มเติมนอกเหนือจากคำตอบอื่น ๆ ในกรณีนี้คำตอบของคุณไม่ได้ให้คุณค่าเพิ่มเติมเนื่องจากมีผู้ใช้รายอื่นโพสต์โซลูชันนั้นแล้ว หากคำตอบก่อนหน้านี้เป็นประโยชน์กับคุณคุณควรลงคะแนนแทนการกรอกข้อมูลเดิมซ้ำ
Toby Speight

คุณไม่คิดว่าฉันอธิบายวิธีแก้ปัญหาที่นี่พร้อมตัวอย่างหรือไม่?
Sijeesh

มีอะไรที่ไม่ครอบคลุมเพียงพอในคำตอบของ John Kugelman ที่เขียนไว้เมื่อ 8 ปีก่อนหรือไม่?
Toby Speight
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.