5

I'm searching a way to be sure my commands are executed by bash on some FreeBSD 11 machines that use csh as default shell.

The following is my code that works on Linux CentOS / Debian / MacOS X / pfSense 2.3 (running on FreeBSD 10.3) and even Windows 10 bash, but doesn't work on FreeBSD 11

cat "/some/filelist" | ssh -i "/home/user/.ssh/some_key" user@freebsd11  'bash -c "while read -r file; do stat -f \"%N;%c;%m\" \"\$file\"; done | sort"'

Output of the previous command on FreeBSD 11 seems to be a csh error message

Unmatched ".

When checking which shell runs, it seems that csh runs. The following returns 'csh'

ssh -i /home/user/.ssh/some_key user@freebsd11 'bash -c "echo $0"'

As of my understandings, BSD systems do not allow changing shell, unless using a heredoc, but I can't send cat "/some/filelist" using a heredoc.

Of course, bash is installed and can be executed. I'm not interested in changing the default shell of the users on FreeBSD.

Any ideas here ?

My best guess would be to divide the problem:

1/ send the file with cat /some/filelist | ssh [..] 'cat > somefile'

2/ use the sent file in a heredoc

ssh [..] 'bash -s' << 'EOF'
while read -r file; do stat -f "%N;%c;%m" "$file" | sort; done < "$somefile"
'EOF'

This solution could work but is messy, makes 2 connections instead of one and won't work if remote can't write the 'somefile' for some reason.

2 Answers 2

3

If you simplify your command line, the shell likely won't matter. This should likely work

ssh </some/filelist -i /home/user/.ssh/some_key user@freebsd11 xargs -n 1 stat -f \"%N;%c;%m\" | sort

Alternatively, you may want to change the default shell to bash for the particular user you are ssh-ing to - see the chsh(1) command.

3
  • Nice, but not space safe. Using ssh </some/filelist -i /home/user/.ssh/some_key user@freebsd11 xargs -I {} stat -f "%N;%c;%m" "{}" | sort would render it space safe. Two questions: 1/ How portable is this ? 2/ xargs is limited in argument size. How can I deal with (very) big file list ? I can't reasonably increase ARG_MAX to a trivial value. Dec 9, 2016 at 7:56
  • xargs runs the command multiple times to avoid limitations on maximum arguments, so can handle a list of arbitrary size. I suggested "-n 1" because I didn't know if stat behaves differently with more than one argument. Dec 9, 2016 at 14:29
  • Yep, after some research, I mistook ARG_MAX and entry size. Dec 9, 2016 at 18:07
2

Use ansible. You don't need to add any additional software on the target machines and, arguably, it simplifies what you need to do. ansible uses standard ssh to connect to the machines, sudo, pfexec or doas are available if you need to run with privileges, and you can choose which user to connect as, and which user to execute as.

If the actual task is to perform stat on a list of files, there's already a module for that, and a lookup to iterate over the lines of a file:

---
- hosts: freebsd11:pfsense
  gather_facts: yes
  tasks:

  - name: stat a list of files
    stat: "{{ item }}"
    with_lines:
     - cat /path/to/list_of_files

If the task is an arbitrary shell command that needs to be executed in the target machine using bash, there's also a module for that:

---
- hosts: freebsd11:pfsense
  gather_facts: yes
  tasks:

  - name: execute shell script using bash
    shell: cat < /tmp/*txt
      args:
        executable: /bin/bash
1
  • Well yes, but, it's basically like trying to kill a fly with a bazooka. Plus, it adds python dependancy which in my user case greatly reduces portability. Still upvoting because it could work. Dec 9, 2016 at 8:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .