Làm thế nào để một nguyên tử thay đổi một liên kết tượng trưng đến một thư mục trong busybox?


18

Tôi đang cố gắng (càng gần càng tốt) về cơ bản thay đổi một liên kết tượng trưng. Tôi đã thử:

ln -sf other_dir existing_symlink

Điều đó chỉ cần đặt symlink mới trong thư mục mà current_symlink đã trỏ tới.

ln -sf other_dir new_symlink
mv -f new_symlink existing_symlink

Điều đó đã làm điều tương tự: nó di chuyển symlink vào thư mục.

cp -s other_dir existing_symlink

Nó từ chối vì đó là một thư mục.

Tôi đã đọc nó mv -Tđược tạo ra cho việc này, nhưng busybox không có -Tcờ.

Câu trả lời:


1

Tôi không thấy làm thế nào bạn có thể có được hoạt động nguyên tử. Trang man cho symlink(2)biết nó đưa ra EEXISTnếu mục tiêu đã tồn tại. Nếu hạt nhân không hỗ trợ hoạt động nguyên tử, giới hạn vùng người dùng của bạn là không liên quan.

Tôi cũng không thấy cách mv -Tgiúp đỡ, ngay cả khi bạn có nó. Hãy thử nó trên một hộp Linux thông thường, một hộp với GNU mv:

$ mkdir a b
$ ln -s a z
$ mv -T b z
mv: cannot overwrite non-directory `z' with directory `b'

Tôi nghĩ rằng bạn sẽ phải làm điều này theo hai bước: xóa liên kết tượng trưng cũ và tạo lại nó.


1
Thật vậy, thật không may, không có cách nào bạn có thể sửa đổi một biểu tượng nguyên tử. Điều tốt nhất bạn có thể làm là xóa liên kết cũ và tạo liên kết mới. GNU coreutils có một tùy chọn để thực hiện điều này với một lệnh ( ln -snf), nhưng vẫn có hai lệnh gọi hệ thống dưới mui xe.
Gilles 'SO- ngừng trở nên xấu xa'

43

Điều này thực sự có thể được thực hiện bằng nguyên tử rename(2), bằng cách đầu tiên tạo liên kết tượng trưng mới dưới tên tạm thời và sau đó ghi đè lên liên kết tượng trưng cũ trong một lần. Như trang người đàn ông nói:

Nếu newpath đề cập đến một liên kết tượng trưng, ​​liên kết sẽ bị ghi đè.

Trong shell, bạn sẽ làm điều này mv -Tnhư sau:

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

Bạn có thể stracethực hiện lệnh cuối cùng để đảm bảo rằng nó thực sự được sử dụng rename(2)dưới mui xe:

$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0

Lưu ý rằng ở trên, cả hai mv -Tstraceđều dành riêng cho Linux.

Trên FreeBSD, sử dụng mv -hluân phiên.


1
Rất đẹp! Có thể hữu ích để nói rằng vào cuối bạn có một liên kết từ z đến b!
Vincenzo Pii

Đối với một giải pháp độc lập với hệ điều hành, hãy sử dụng ngôn ngữ kịch bản có khả năng sử dụng renametrực tiếp tòa nhà thay vì mv -hhoặc mv -T. Ví dụ với Perl:perl -e 'rename "z.new", "z" or die $!'
Slaven Rezic

8

Chọn nơi Arto rời khỏi đây, điều này là hoàn toàn có thể, thậm chí không cần mv -T, bạn chỉ cần tạo một liên kết tượng trưng mới có cùng tên với thư mục đích và mvnó vào thư mục mẹ của mục tiêu của bạn:

mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./

Ví dụ mã được thực hiện thông qua ( http://icularcorps.wordpress.com/2013/07/03/atomively-replaces-files-and-directories/ )


3

Bạn đã thử ln -snfchưa

Tùy chọn -nghi đè đích đến thay vì ghi bên dưới khi đích là một liên kết tượng trưng đến một thư mục.

Chúc mừng


3
ln -snfkhông phải là nguyên tử: nó hủy liên kết đích, sau đó tạo liên kết tượng trưng mong muốn.
Gilles 'SO- ngừng trở nên xấu xa'

2
Cho rằng OP đã quan tâm đến việc "gần như possib [e]" để thay đổi nguyên tắc một liên kết tượng trưng, ​​đây là một câu trả lời hoàn toàn hợp lý. Nếu có một nguyên tử tốt hơn có thể tiến gần hơn (hoặc là) nguyên tử, thì đó có thể được chấp nhận. Tôi không nghĩ rằng cần phải downvote.
Wilco
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.