У меня пока недостаточно баллов, чтобы прокомментировать другой ответ, но, основываясь на вашей ветке комментариев, вам нужно удалить или исправить сломанные пакеты (простой способ — просто удалить, поэтому запуститеsudo apt-get remove 389-ds-console
)
Как я сказал в своем ответе, посмотрите на сообщения об ошибках, которые вы получаете, они точно говорят вам, что не так и что вам нужно сделать.
Насколько мне известно, нет способа заставить Bash принимать окончание строк в стиле Windows -.
В ситуациях, связанных с Windows, обычной практикой является полагаться на способность Git автоматически преобразовывать окончания строк -при фиксации, используя флаг конфигурации autocrlf
. См., например, документацию GitHub по окончаниям строк , которая не относится к GitHub. Таким образом, файлы фиксируются в репозитории с окончанием строки в стиле Unix -и преобразуются соответствующим образом для каждой клиентской платформы.
(Противоположная проблема не является проблемой. :MSYS2 отлично работает с окончаниями строк в стиле Unix -в Windows.)
Для этого следует использовать binfmt _misc [1].
Сначала определите магию, которая обрабатывает файлы, начинающиеся с #! /bin/bash<CR><LF>
, затем создайте для нее исполняемый интерпретатор. Интерпретатором может быть другой скрипт:
INTERP=/path/to/bash-crlf
echo ",bash-crlf,M,,#! /bin/bash\x0d\x0a,,$INTERP," > /proc/sys/fs/binfmt_misc/register
cat > "$INTERP" <<'EOT'; chmod 755 "$INTERP"
#! /bin/bash
script=$1; shift; exec bash <(sed 's/\r$//' "$script") "$@"
EOT
Проверь:
$ printf '%s\r\n' '#! /bin/bash' pwd >/tmp/foo; chmod 755 /tmp/foo
$ cat -v /tmp/foo
#! /bin/bash^M
pwd^M
$ /tmp/foo
/tmp
У примера интерпретатора есть две проблемы:1. поскольку он передает скрипт через -недоступный для поиска файл (канал ), bash будет читать его побайтно, очень неэффективно, и 2. любые сообщения об ошибках будут ссылаться на /dev/fd/63
или подобное вместо имени исходного скрипта.
[1] Конечно, вместо использования binfmt _misc вы можете просто создать /bin/bash^M
символическую ссылку на интерпретатор, которая также будет работать в других системах, таких как OpenBSD:
ln -s /path/to/bash-crlf $'/bin/bash\r'
Но в Linux исполняемые файлы shebanged не имеют преимуществ перед binfmt _misc, и размещение мусора внутри системных каталогов — неправильная стратегия, и любой системный администратор заставит качать головой ;-)
Хорошо, я нашел обходной путь через:
"Соединенные" символические ссылки
Modern unix systems have a way to make arbitrary data appear as a file, independently of how it's stored: FUSE. With FUSE, every operation on a file (create, open, read, write, list directory, etc.) invokes some code in a program, and that code can do whatever you want. See Create a virtual file that is actually a command. You could try out scriptfs or fuseflt, or if you're feeling ambitious, roll your own.
... и Создать виртуальный файл, который на самом деле является командой
You may be looking for a named pipe.
Таким образом, это подход :создать именованный канал, получить dos2unix
вывод в него, а затем bash
вызвать именованный канал.
Здесь у меня есть оригинал tmp.sh
с окончаниями строки CRLF в /tmp
; кулак, давайте создадим именованный канал:
tmp$ mkfifo ftmp.sh
Теперь, если вы запустите эту команду:
tmp$ dos2unix <tmp.sh >ftmp.sh
... вы заметите, что он блокируется; тогда, если вы это сделаете, скажите:
~$ cat /tmp/ftmp.sh | hexdump -C
00000000 65 63 68 6f 20 22 74 65 73 74 69 6e 67 22 0a 73 |echo "testing".s|
00000010 74 61 74 20 2e 0a 65 63 68 6f 20 22 74 65 73 74 |tat..echo "test|
00000020 69 6e 67 20 61 67 61 69 6e 22 0a |ing again".|
0000002b
... вы заметите, что преобразование было выполнено -и после того, как команда cat
выполнила свою работу, команда dos2unix <tmp.sh >ftmp.sh
, которая ранее была заблокирована, завершилась.
Итак, мы можем настроить dos2unix
запись в именованный канал в «бесконечном» цикле while:
tmp$ while [ 1 ] ; do dos2unix <tmp.sh >ftmp.sh ; done
... и даже если это «жесткий» цикл, это не должно быть проблемой, так как большую часть времени команда внутри цикла while блокируется.
Тогда я смогу:
~$ bash /tmp/ftmp.sh
testing
File:.
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 801h/2049d Inode: 5276132 Links: 7
...
testing again
$
... и ясно, что скрипт работает нормально.
Что хорошо в этом подходе, так это то, что я могу открыть оригинал tmp.sh
в текстовом редакторе; и напишите новый код -с окончаниями CRLF -, затем сохраните tmp.sh
; и запуск bash /tmp/ftmp.sh
под Linux запустит последнюю сохраненную версию.
Проблема в том, что такие команды, как read -p "Enter user: " user
, которые полагаются на стандартный ввод терминала, не будут выполняться; вернее, не провалится, а если попробуешь, скажи так/tmp/tmp.sh
echo "testing"
stat.
echo "testing again"
read -p "Enter user: " user
echo "user is: $user"
... то это будет вывод:
$ bash /tmp/ftmp.sh
testing
File:.
Size: 4096 Blocks: 8 IO Block: 4096 directory
...
Birth: -
testing again
Enter user: tyutyu
user is: tyutyu
testing
File:.
Size: 4096 Blocks: 8 IO Block: 4096 directory
...
Birth: -
testing again
Enter user: asd
user is: asd
testing
...
... и так далее -то есть stdin с клавиатуры в терминале интерпретируется правильно, но по какой-то причине скрипт начинает зацикливаться, и выполняется с самого начала снова и снова (чего не происходит, если у нас нет команды read -p...
в оригинале tmp.sh
). Может быть, есть какие-то вещи для перенаправления (, например. добавление некоторого ;на самом деле, у меня был скрипт 0>1&
или чего-то еще к while
команде цикла .sh
с wget
, который также начинал зацикливаться, и простое добавление явного exit
в конец скрипта .sh
, похоже, работало, чтобы остановить цикл скрипта ), который мог обрабатывать это тоже, -, но пока скрипт, который мне нужно использовать, не имеет read -p
подобных команд, поэтому этот подход может сработать для меня.
Вы можете вставить решетку (#)в конце каждой строки в ваших bash-скриптах. Таким образом, оболочки в Unix будут рассматривать CR просто как комментарий и не будут обращать на него внимания.
"Hex-говорение", любая строка должна заканчиваться
0x23 0x0D 0x0A
Пример:
echo "testing" #
stat. #
echo "testing again" #