0

If i run in bash script (similar to this one) to send content to a file:

sudo ./bar.sh > foo

content bar.sh:

echo 'for pid in $(ps -ef | grep "smbd" | awk '{print $2}'); do kill -9 $pid &> /dev/null; done'

foo out:

for pid in $(ps -ef | grep "smbd" | awk {print }); do kill -9 $pid &> /dev/null; done

$2 is lost in out.

expected output:

for pid in $(ps -ef | grep "smbd" | awk '{print $2}'); do kill -9 $pid &> /dev/null; done

How do I get it?

acgbox
  • 941
  • Your quoting is strange and looks unbalanced. What is the point of the echo? – user10489 Dec 30 '21 at 13:40
  • Don't use single quotes - they prevent shell expansion (as you see). – RudiC Dec 30 '21 at 13:41
  • It is usually redundant to use awk and grep in the same pipeline. You can merge the grep into awk. – user10489 Dec 30 '21 at 13:42
  • 2
    What is the final output you are expecting? You are doing things in a very, very complicated way so it isn't clear what you really need here. What should the final output look like? Are you trying to write a script whose output is another script? If you explain what the final objective is, we can help you better. – terdon Dec 30 '21 at 13:51
  • I apologize. I wanted to put the complete command to be able to justify the echo ' ' – acgbox Dec 30 '21 at 13:53
  • you can post the full answer, to review it and select it if it works. Thanks – acgbox Dec 30 '21 at 13:58
  • OK. Please just add the output you are expecting. What do you want foo to contain? – terdon Dec 30 '21 at 13:59
  • @terdon update with expected output: – acgbox Dec 30 '21 at 14:01
  • What's the point of a having a script (bar.sh) if it only outputs a fixed string? You could just put that string in a file and run cat bar.txt > foo instead. Or just edit it into foo directly. – ilkkachu Dec 30 '21 at 14:08
  • This I posted is just a snippet of the script (the part of the problem). I can't change it because "foo" is actually a script to which many commands are added depending on what the user wants, and it is programmed in crontab. So I can't change it. I just need to fix the published part – acgbox Dec 30 '21 at 14:20

1 Answers1

5

First of all, never run things with sudo unless it is actually necessary to run them with sudo. I really cannot emphasize that enough. Unless you get a "permission denied" error, you don't need sudo and you should not use sudo. So you don't need sudo ./bar.sh, just run ./bar.sh.

Next, you don't need to echo to get the results of a command. This isn't needed:

echo '$(ps -ef | grep "smbd" | awk '{print $2}')'

All you need is to run the command itself. You don't need the command substitution ($(command)) or the echo. Just have this in your script:

ps -ef | grep "smbd" | awk '{print $2}'

Note that if you want to get the PID of a running process, you don't really want ps either. You can just use pgrep smbd which avoids the problem of the grep process itself appearing in the results.

Finally, if you want to print a multi-line string as output, you can use a here doc instead of many echo statements. So, putting all that together, you should make bar.sh like this:

#!/bin/sh

cat <<'EoF' for pid in $(ps -ef | grep "smbd" | awk '{print $2}'); do kill -9 "$pid" &> /dev/null done EoF

And then run it as ./bar.sh > foo (no sudo!).

Or, here's a simpler version of the same approach:

#!/bin/sh

cat <<'EoF' ps -ef | awk '/smbd/{print $2}' | while read pid; do kill -9 "$pid" &> /dev/null done EoF

Or, even simpler:

#!/bin/sh

printf '%s\n' 'kill -9 $(pgrep smbd)'

Which brings us to the final point of are you sure you really want a script for this? To kill all running smbd processes, all you need is a single command:

pkill -9 smbd
terdon
  • 242,166
  • <<'EoF' or so if you want the here-doc passed as-is. (Not that I still understand what the point of the whole exercise is.) – ilkkachu Dec 30 '21 at 14:17
  • Of course, thanks @ilkkachu. And no, I don't really see the point either but there may be a special need we're not aware of. – terdon Dec 30 '21 at 14:19
  • @ajcg how does this not fix what you posted? Just use the here string approach and you can print whatever you want. The first example I give should produce exactly the output you are looking for. – terdon Dec 30 '21 at 14:25
  • cat <<'EoF' It is not the answer I was looking for, but it solves my problem. Thanks – acgbox Dec 30 '21 at 14:26
  • 1
    @ajcg the answer you were looking for is this: echo 'for pid in $(ps -ef | grep "smbd" | awk '{print \$2}'); do kill -9 $pid &> /dev/null; done'. You need to escape the $2 with \$2. But use the heredoc instead it is easier and more powerful. – terdon Dec 30 '21 at 14:28
  • @terdon yeah that was what I was looking for. Great job. Thank you. Both solutions fix the problem – acgbox Dec 30 '21 at 14:34
  • Unless there's a really good reason, the -9 is not needed. See e.g. https://unix.stackexchange.com/questions/8916 – Kusalananda Dec 30 '21 at 18:46